@zh-moody/safe-env 0.4.0 → 0.4.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/README.en.md +86 -50
- package/README.md +62 -13
- package/dist/chunk-5KPNMU6R.js +1 -0
- package/dist/chunk-6NHVLNFI.cjs +9 -0
- package/dist/chunk-JBML47XC.js +9 -0
- package/dist/chunk-TR6KYAQI.cjs +1 -0
- package/dist/fs-browser.cjs +1 -1
- package/dist/fs-browser.js +1 -1
- package/dist/fs-node.cjs +1 -1
- package/dist/fs-node.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +22 -8
- package/dist/index.d.ts +22 -8
- package/dist/index.js +1 -1
- package/dist/{types-Bx-JEkTH.d.cts → types-BsDPVktI.d.cts} +11 -8
- package/dist/{types-Bx-JEkTH.d.ts → types-BsDPVktI.d.ts} +11 -8
- package/dist/vite.cjs +1 -1
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-7CVG4I6F.js +0 -1
- package/dist/chunk-D6WM53FN.cjs +0 -1
- package/dist/chunk-I7AUKTXE.js +0 -1
- package/dist/chunk-K2JQKLKN.js +0 -9
- package/dist/chunk-PBYVLIUG.cjs +0 -9
- package/dist/chunk-PLO26PP5.cjs +0 -1
package/README.en.md
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
[简体中文](./README.md) | English
|
|
8
8
|
|
|
9
|
-
**Say goodbye to `undefined`! Intercept all configuration
|
|
9
|
+
**Say goodbye to `undefined`! Intercept all configuration hazards on the first line of your app.**
|
|
10
10
|
|
|
11
|
-
Whether you
|
|
11
|
+
Whether you're building with Vue, React, or Node.js, environment variables are often the root of production incidents. `safe-env` ensures your application always runs on top of expected configurations through strong schema validation and runtime protection.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -16,14 +16,14 @@ Whether you are writing Vue, React, or Node.js, environment variables are often
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
### 🚀
|
|
19
|
+
### 🚀 Key Features
|
|
20
20
|
|
|
21
|
-
- **Build-time
|
|
22
|
-
- **Sensitive Data Masking**: Supports `.secret()` to ensure keys
|
|
23
|
-
- **Runtime
|
|
24
|
-
- **Monorepo Ready**:
|
|
25
|
-
- **IDE Enhancement**:
|
|
26
|
-
- **
|
|
21
|
+
- **Build-time Pre-validation**: Vite plugin intercepts invalid configurations during dev startup or build.
|
|
22
|
+
- **Sensitive Data Masking**: Supports `.secret()` to ensure keys/tokens are masked in logs or error reports.
|
|
23
|
+
- **Runtime Lazy Protection**: ⚡ **HPC Ready**. Powered by **Lazy Proxy**, achieving $O(1)$ startup latency and on-demand read-only protection.
|
|
24
|
+
- **Monorepo Ready**: Explicitly specify `.env` search directories via `cwd`, fitting complex architectures.
|
|
25
|
+
- **IDE Enhancement**: `.description()` allows you to view variable purposes/documentation via hover.
|
|
26
|
+
- **Robust Parsing**: Built-in `s.array()`, `s.boolean()` with intelligent conversion and `.transform()` pipe processing.
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -37,9 +37,15 @@ npm install @zh-moody/safe-env
|
|
|
37
37
|
|
|
38
38
|
### 🚀 Quick Start
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Ensure you have a **`.env`** file in your project root before starting:
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
```bash
|
|
43
|
+
# .env example
|
|
44
|
+
VITE_API_URL=https://api.example.com
|
|
45
|
+
VITE_PORT=8080
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### 🔹 [Vite / React / Vue] Usage
|
|
43
49
|
|
|
44
50
|
**1. Configure Vite Plugin (`vite.config.ts`):**
|
|
45
51
|
|
|
@@ -52,14 +58,14 @@ export default {
|
|
|
52
58
|
};
|
|
53
59
|
```
|
|
54
60
|
|
|
55
|
-
**2. Define and Export
|
|
61
|
+
**2. Define and Export Schema (`src/env.ts`):**
|
|
56
62
|
|
|
57
63
|
```typescript
|
|
58
|
-
import { safeEnv, s } from "@zh-moody/safe-env";
|
|
64
|
+
import { safeEnv, s, isUrl } from "@zh-moody/safe-env";
|
|
59
65
|
|
|
60
66
|
export const schema = {
|
|
61
|
-
VITE_API_URL: s.string().
|
|
62
|
-
VITE_PORT: s.number(3000).description("
|
|
67
|
+
VITE_API_URL: s.string().validate(isUrl, "Invalid URL").description("Backend API endpoint"),
|
|
68
|
+
VITE_PORT: s.number(3000).description("Server port"),
|
|
63
69
|
};
|
|
64
70
|
|
|
65
71
|
export const env = safeEnv(schema, {
|
|
@@ -67,33 +73,22 @@ export const env = safeEnv(schema, {
|
|
|
67
73
|
});
|
|
68
74
|
```
|
|
69
75
|
|
|
70
|
-
> **💡 Best Practice: Prevent Vite Type Pollution**
|
|
71
|
-
> To completely disable the insecure original `import.meta.env.XXX` hints, modify `src/vite-env.d.ts`:
|
|
72
|
-
>
|
|
73
|
-
> ```typescript
|
|
74
|
-
> interface ImportMetaEnv {
|
|
75
|
-
> [key: string]: never;
|
|
76
|
-
> }
|
|
77
|
-
> ```
|
|
78
|
-
|
|
79
76
|
---
|
|
80
77
|
|
|
81
|
-
#### 🔸 [Node.js / Server-side]
|
|
78
|
+
#### 🔸 [Node.js / Server-side] Usage
|
|
82
79
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
**1. Define Config (`src/config.ts`):**
|
|
80
|
+
**1. Define Configuration (`src/config.ts`):**
|
|
86
81
|
|
|
87
82
|
```typescript
|
|
88
83
|
import { safeEnv, s } from "@zh-moody/safe-env";
|
|
89
84
|
|
|
90
85
|
const config = safeEnv(
|
|
91
86
|
{
|
|
92
|
-
DB_PASSWORD: s.string().secret().description("Database
|
|
87
|
+
DB_PASSWORD: s.string().secret().description("Database password"),
|
|
93
88
|
DB_PORT: s.number(5432).min(1).max(65535),
|
|
94
89
|
},
|
|
95
90
|
{
|
|
96
|
-
// Explicitly specify
|
|
91
|
+
// Explicitly specify .env root in Monorepo or deployment environments
|
|
97
92
|
// cwd: '/path/to/project-root'
|
|
98
93
|
},
|
|
99
94
|
);
|
|
@@ -105,59 +100,100 @@ export default config;
|
|
|
105
100
|
|
|
106
101
|
### 🛠️ API Reference
|
|
107
102
|
|
|
108
|
-
#### 1.
|
|
103
|
+
#### 1. Global Options (`safeEnv`)
|
|
104
|
+
|
|
105
|
+
`safeEnv(schema, options?)` accepts an optional object to control the parsing engine:
|
|
106
|
+
|
|
107
|
+
- **`useCache (boolean)`**: Enable global memoization (default `true`). Significantly improves performance for high-frequency calls.
|
|
108
|
+
- **`refreshCache (boolean)`**: Force flush and re-read disk/process variables (default `false`). Essential for HMR or switching envs in automated tests.
|
|
109
|
+
- **`cwd (string)`**: Specify the search root for `.env` files (Node.js).
|
|
110
|
+
- **`source (Record<string, any>)`**: Manually provide the data source (e.g., `import.meta.env`), skipping automatic file retrieval.
|
|
111
|
+
- **`prefix (string)`**: Filter prefix for env variables (default `VITE_`).
|
|
112
|
+
|
|
113
|
+
#### 2. Field Definitions (`s.xxx`)
|
|
109
114
|
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
- `
|
|
114
|
-
-
|
|
115
|
+
- **`s.string(default?)`**:
|
|
116
|
+
- **Logic**: If no default is provided, it's marked as **Required**.
|
|
117
|
+
- **`s.number(default?)`**:
|
|
118
|
+
- **Logic**: Executes `Number(v)`. Aborts with an error if result is `NaN` (e.g., `VITE_PORT=abc`).
|
|
119
|
+
- **`s.boolean(default?)`**: Intelligent Boolean parsing.
|
|
120
|
+
- **Logic**:
|
|
121
|
+
- **`true`**: `true`, `"true"`, `"1"`, `"yes"`, `"on"`.
|
|
122
|
+
- **`false`**: `false`, `"false"`, `"0"`, `"no"`, `"off"`, or empty strings.
|
|
123
|
+
- **`s.array(default?, separator?)`**:
|
|
124
|
+
- **Logic**: Default separator is `,`. Supports custom ones like `s.array([], '|')`.
|
|
125
|
+
- **`s.enum(options, default?)`**:
|
|
126
|
+
- **Logic**: Input must be one of the `options`. Perfect for mode locking (`dev`, `prod`, `test`).
|
|
115
127
|
|
|
116
|
-
####
|
|
128
|
+
#### 3. Enhancements & Validation (Chaining)
|
|
117
129
|
|
|
118
|
-
- **`.secret()`**:
|
|
130
|
+
- **`.secret()`**: Mask sensitive data in error reports (`********`).
|
|
119
131
|
```typescript
|
|
120
132
|
PASSWORD: s.string().secret();
|
|
121
133
|
```
|
|
122
|
-
- **`.
|
|
134
|
+
- **`.description(text)`**: Hover hints for IDEs.
|
|
123
135
|
```typescript
|
|
124
|
-
|
|
136
|
+
PORT: s.number(3000).description("Server port");
|
|
125
137
|
```
|
|
126
|
-
- **`.
|
|
138
|
+
- **`.optional()`**: Explicitly declare this field as optional. Missing values drop back to `undefined` instead of throwing an error.
|
|
127
139
|
```typescript
|
|
128
|
-
|
|
140
|
+
TRACKING_ID: s.string().optional();
|
|
129
141
|
```
|
|
130
|
-
- **`.
|
|
142
|
+
- **`.requiredIf(fn)`**: Context-Aware validation. Dynamically determine if the field is required based on values parsed so far.
|
|
131
143
|
```typescript
|
|
132
|
-
|
|
144
|
+
// ICP_NUMBER is required ONLY if parsed REGION equals 'CN'
|
|
145
|
+
ICP_NUMBER: s.string().requiredIf((ctx) => ctx.parsed.REGION === 'CN');
|
|
133
146
|
```
|
|
134
|
-
- **`.transform(fn)`**: Custom data transformation
|
|
147
|
+
- **`.transform(fn)`**: Custom data transformation (Multi-level pipe).
|
|
135
148
|
```typescript
|
|
136
149
|
NAME: s.string()
|
|
137
150
|
.transform((v) => v.trim())
|
|
138
151
|
.transform((v) => v.toUpperCase());
|
|
139
152
|
```
|
|
140
|
-
- **`.from(key)`**:
|
|
153
|
+
- **`.from(key)`**: Alias mapping (Environment key mapping).
|
|
141
154
|
```typescript
|
|
142
155
|
port: s.number().from("VITE_SERVER_PORT");
|
|
143
156
|
```
|
|
144
|
-
- **`.min(n)` / `.max(n)`**:
|
|
157
|
+
- **`.min(n)` / `.max(n)`**: Number range constraints.
|
|
145
158
|
```typescript
|
|
146
159
|
PORT: s.number().min(1024).max(65535);
|
|
147
160
|
```
|
|
148
|
-
- **`.validate(fn, msg?)`**:
|
|
161
|
+
- **`.validate(fn, msg?)`**: Custom logic validation. Supports context passing and native pure-function integration (See "Built-in Validation Rules").
|
|
149
162
|
```typescript
|
|
150
163
|
INTERNAL_URL: s.string().validate(
|
|
151
|
-
(v) => v.endsWith(".internal.com"),
|
|
164
|
+
(v, ctx) => v.endsWith(".internal.com"),
|
|
152
165
|
"Must be internal",
|
|
153
166
|
);
|
|
154
167
|
```
|
|
155
168
|
|
|
169
|
+
#### 4. Built-in Validation Rules
|
|
170
|
+
|
|
171
|
+
To support an infinite amount of business validation logic without blowing up bundle sizes, all heavy string validators (like Regex) and transformers are separated from the core class. They are instead provided as **pure, perfectly tree-shakable higher-order functions** that can be imported directly.
|
|
172
|
+
|
|
173
|
+
Seamlessly integrate them using native `validate`/`transform` methods:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { safeEnv, s, isUrl, isIPv4, isUUID, isJSON, toJSON, trim } from "@zh-moody/safe-env";
|
|
177
|
+
|
|
178
|
+
const schema = {
|
|
179
|
+
// Dirty data processing: Trim whitespaces, then validate IPv4
|
|
180
|
+
HOST: s.string().transform(trim).validate(isIPv4, "Must be valid IPv4"),
|
|
181
|
+
// Serialization mapping natively
|
|
182
|
+
PAYLOAD: s.string().validate(isJSON).transform(toJSON),
|
|
183
|
+
// Common URL link checking
|
|
184
|
+
API_URL: s.string().validate(isUrl, "Must be a valid URL")
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Currently, `@zh-moody/safe-env` exports the following utility functions out-of-the-box:
|
|
189
|
+
- **Validators**: `isUrl`, `isEmail`, `isIPv4`, `isUUID`, `isBase64`, `isJSON`, `isHexColor`, `isObjectId`, `matchesRegex(pattern)`
|
|
190
|
+
- **Transformers**: `trim`, `toLowerCase`, `toUpperCase`, `toJSON`
|
|
191
|
+
|
|
156
192
|
---
|
|
157
193
|
|
|
158
194
|
### 🎨 Error Reporting
|
|
159
195
|
|
|
160
|
-
When validation fails, `safe-env` outputs
|
|
196
|
+
When validation fails, `safe-env` outputs an adaptive structured table showing: **Key / Error / Current Value (Masked)**.
|
|
161
197
|
|
|
162
198
|
---
|
|
163
199
|
|
package/README.md
CHANGED
|
@@ -37,6 +37,14 @@ npm install @zh-moody/safe-env
|
|
|
37
37
|
|
|
38
38
|
### 🚀 快速上手
|
|
39
39
|
|
|
40
|
+
在开始之前,请确保你的项目根目录下已有相应的 **`.env`** 配置文件:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# .env 示例
|
|
44
|
+
VITE_API_URL=https://api.example.com
|
|
45
|
+
VITE_PORT=8080
|
|
46
|
+
```
|
|
47
|
+
|
|
40
48
|
#### 🔹 [Vite / React / Vue] 使用
|
|
41
49
|
|
|
42
50
|
在前端,建议配合 Vite 插件实现**构建时校验**。
|
|
@@ -105,15 +113,33 @@ export default config;
|
|
|
105
113
|
|
|
106
114
|
### 🛠️ API 详解
|
|
107
115
|
|
|
108
|
-
#### 1.
|
|
116
|
+
#### 1. 全局配置与选项 (`safeEnv`)
|
|
117
|
+
|
|
118
|
+
`safeEnv(schema, options?)` 接收一个可选的配置对象,用于深度控制解析行为:
|
|
119
|
+
|
|
120
|
+
- **`useCache (boolean)`**: 是否启用全局缓存(默认 `true`)。开启后,后续调用将优先从内存获取已解析的配置,极大提升高频调用的性能。
|
|
121
|
+
- **`refreshCache (boolean)`**: 强制刷新并重新读取磁盘/进程变量(默认 `false`)。常用于开发环境下的热更新或自动化测试中切换不同的环境配置。
|
|
122
|
+
- **`cwd (string)`**: 显式指定 `.env` 文件的检索根目录(Node.js 环境)。
|
|
123
|
+
- **`source (Record<string, any>)`**: 手动指定数据源(如 `import.meta.env` 或 `process.env`),跳过自动文件检索。
|
|
124
|
+
- **`prefix (string)`**: 过滤环境变量的前缀(默认 `VITE_`)。
|
|
125
|
+
|
|
126
|
+
#### 2. 定义字段 (`s.xxx`)
|
|
109
127
|
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
- `
|
|
114
|
-
-
|
|
128
|
+
- **`s.string(default?)`**: 字符串解析。
|
|
129
|
+
- **逻辑**: 如果不提供默认值,该字段将被标记为 **必填 (Required)**,若 `.env` 中缺失会触发报错。
|
|
130
|
+
- **`s.number(default?)`**: 数字解析。
|
|
131
|
+
- **逻辑**: 自动执行 `Number(v)`。若转换结果为 `NaN`(如 `VITE_PORT=abc`),解析会立即中止并报错。
|
|
132
|
+
- **`s.boolean(default?)`**: 增强布尔解析。
|
|
133
|
+
- **逻辑**: 支持多种真假语义的自动转换:
|
|
134
|
+
- **`true`**: `true`, `"true"`, `"1"`, `"yes"`, `"on"`。
|
|
135
|
+
- **`false`**: `false`, `"false"`, `"0"`, `"no"`, `"off"`, 以及空字符串。
|
|
136
|
+
- **`s.array(default?, separator?)`**: 数组解析。
|
|
137
|
+
- **逻辑**: 默认使用 `,` 作为分隔符。支持自定义,如 `s.array([], '|')`。
|
|
138
|
+
- **示例**: `VITE_MODS=auth,cache` ➡️ `['auth', 'cache']`。
|
|
139
|
+
- **`s.enum(options, default?)`**: 枚举约束。
|
|
140
|
+
- **逻辑**: 强制输入值必须在 `options` 数组中,否则报错。非常适用于多环境(`dev`, `prod`, `test`)的模式锁定。
|
|
115
141
|
|
|
116
|
-
####
|
|
142
|
+
#### 3. 校验与增强 (链式调用)
|
|
117
143
|
|
|
118
144
|
每个字段都可以通过链式调用进行深度定制:
|
|
119
145
|
|
|
@@ -121,13 +147,14 @@ export default config;
|
|
|
121
147
|
```typescript
|
|
122
148
|
PASSWORD: s.string().secret();
|
|
123
149
|
```
|
|
124
|
-
- **`.
|
|
150
|
+
- **`.optional()`**: 显式声明该字段为非必填。解析如果不存在,则返回 `undefined` 而不报错。
|
|
125
151
|
```typescript
|
|
126
|
-
|
|
152
|
+
TRACKING_ID: s.string().optional();
|
|
127
153
|
```
|
|
128
|
-
- **`.
|
|
154
|
+
- **`.requiredIf(fn)`**: 联动校验(Context-Aware)。依据当前已解析的其他配置动态决定该字段是否必填。
|
|
129
155
|
```typescript
|
|
130
|
-
|
|
156
|
+
// 只有当 REGION 明确被设为 CN 时,ICP 备案号才是必填的
|
|
157
|
+
ICP_NUMBER: s.string().requiredIf((ctx) => ctx.parsed.REGION === 'CN');
|
|
131
158
|
```
|
|
132
159
|
- **`.description(text)`**: 添加变量描述,映射到 IDE 悬停提示中。
|
|
133
160
|
```typescript
|
|
@@ -147,14 +174,36 @@ export default config;
|
|
|
147
174
|
```typescript
|
|
148
175
|
PORT: s.number().min(1024).max(65535);
|
|
149
176
|
```
|
|
150
|
-
- **`.validate(fn, msg?)`**:
|
|
177
|
+
- **`.validate(fn, msg?)`**: 传入纯函数进行校验。支持上下文透传以及库内置高阶纯函数的直接切入(详情见下文 "内置验证库")。
|
|
151
178
|
```typescript
|
|
152
179
|
INTERNAL_URL: s.string().validate(
|
|
153
|
-
(v) => v.endsWith(".internal.com"),
|
|
180
|
+
(v, ctx) => v.endsWith(".internal.com"),
|
|
154
181
|
"Must be internal",
|
|
155
182
|
);
|
|
156
183
|
```
|
|
157
184
|
|
|
185
|
+
#### 4. 内置验证库
|
|
186
|
+
|
|
187
|
+
为了支持无限的业务规则而不造成构建体积膨胀,所有重型字符串校验(长正则)和转换规则均剔除出了核心类,化作了**支持完美 Tree-Shaking 的扁平化导出的高阶函数**。只有你明确通过 `import` 引用的微小单点代码才会被真正打包!
|
|
188
|
+
|
|
189
|
+
使用原生 `validate`/`transform` 方法无隙集成它们:
|
|
190
|
+
```typescript
|
|
191
|
+
import { safeEnv, s, isUrl, isIPv4, isUUID, isJSON, toJSON, trim } from "@zh-moody/safe-env";
|
|
192
|
+
|
|
193
|
+
const schema = {
|
|
194
|
+
// 脏数据清理:先裁剪首尾空格、后校验 IPv4 格式
|
|
195
|
+
HOST: s.string().transform(trim).validate(isIPv4, "必需是合法 IPv4"),
|
|
196
|
+
// 支持链式序列化
|
|
197
|
+
PAYLOAD: s.string().validate(isJSON).transform(toJSON),
|
|
198
|
+
// 甚至只是普通的链接和格式判定
|
|
199
|
+
API_URL: s.string().validate(isUrl, "必须抛出无效链接")
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
目前的 `@zh-moody/safe-env` 原生伴随导出了以下优质清洗函数组合,按需使用即可:
|
|
204
|
+
- **Validators (验证器)**: `isUrl`, `isEmail`, `isIPv4`, `isUUID`, `isBase64`, `isJSON`, `isHexColor`, `isObjectId`, `matchesRegex(pattern)`
|
|
205
|
+
- **Transformers (转换器)**: `trim`, `toLowerCase`, `toUpperCase`, `toJSON`
|
|
206
|
+
|
|
158
207
|
---
|
|
159
208
|
|
|
160
209
|
### 🎨 错误报告
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import u from"fs";import a from"path";function m(r){let n={},i=r.split(/\r?\n/);for(let d of i){let e=d.trim();if(!e||e.startsWith("#"))continue;let o=e.indexOf("=");if(o===-1)continue;let s=e.slice(0,o).trim(),t=e.slice(o+1).trim();if(!t){n[s]="";continue}let c=t[0];if(c==='"'||c==="'"){let l=t.indexOf(c,1);if(l!==-1){n[s]=t.slice(1,l);continue}}let f=t.indexOf("#");f!==-1&&(t=t.slice(0,f).trim()),n[s]=t}return n}function h(r=".env",n){try{let i=a.resolve(n||process.cwd(),r);if(u.existsSync(i))return m(u.readFileSync(i,"utf-8"))}catch{}return{}}export{m as a,h as b};
|
|
@@ -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 F="development",j= exports.b ="serve",K= exports.c ="build",C= exports.d ="VITE_DEV_SERVER",k= exports.e ="VITE_";var O=typeof window<"u"&&typeof window.document<"u";function b(i,o=!0){if(O)return`SafeEnv Validation Failed: ${i.map(s=>`${s.key} (${s.error})`).join(", ")}`;let d={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},n=(s,p)=>{let r=String(s),x=()=>r.length+(r.match(/[^\x00-\xff]/g)||[]).length;for(;x()>p;)r=r.slice(0,-1);return r+" ".repeat(p-x())},c=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,u=Math.floor(c*.3),y=Math.floor(c*.5),e=o?d:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},f=`
|
|
2
|
+
${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}
|
|
3
|
+
`;return f+=` ${e.b}${n("Key",u)} \u2502 ${n("Error",y)} \u2502 Value${e.res}
|
|
4
|
+
`,f+=e.d+"\u2500".repeat(c+5)+e.res+`
|
|
5
|
+
`,i.forEach(s=>{let p=s.value===void 0?"undefined":s.isSecret?"********":`"${s.value}"`,r=s.value===void 0?e.d:s.isSecret?e.y:e.cy;f+=` ${e.y}${n(s.key,u)}${e.res} \u2502 ${e.r}${n(s.error,y)}${e.res} \u2502 ${r}${p}${e.res}
|
|
6
|
+
`}),f+=e.d+"\u2500".repeat(c+5)+e.res+`
|
|
7
|
+
`,f+=` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
|
|
8
|
+
`,f}function _(i){if(O){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let o=i.reduce((d,n)=>(d[n.key]={"Error Message":n.error,"Current Value":n.value===void 0?"undefined":n.isSecret?"********":n.value},d),{});console.table(o),console.log("%c \u{1F4A1} Tip: Check your .env files or schema definitions. ","color: #059669; font-style: italic;"),console.groupEnd()}else console.error(b(i,!0))}var l={},$=new WeakMap;function P(i){let o=b(i,!1);return new Proxy({},{get(d,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
|
+
${o}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}var w="[safe-env] Cannot modify read-only environment variables.";function I(i){if($.has(i))return $.get(i);let o=new Proxy(i,{get(d,n){if(n==="__isSafeEnv")return!0;let c=Reflect.get(d,n);return c!==null&&typeof c=="object"&&!Object.isFrozen(c)?I(c):c},set(){throw new Error(w)},deleteProperty(){throw new Error(w)},defineProperty(){throw new Error(w)},setPrototypeOf(){throw new Error(w)}});return $.set(i,o),o}function X(i,o={}){let{loadProcessEnv:d=!0,prefix:n=k,cwd:c,useCache:u=!0,refreshCache:y=!1,envLoader:e}=o;if(y)for(let t in l)delete l[t];let f=typeof window<"u",s=typeof process<"u"&&(!!process.env.VITE||!!process.env[C]),p=f||s||"source"in o,r={},x=!1;if("source"in o)o.source===void 0?(x=!0,r={}):r=o.source;else if(u&&!y&&Object.keys(l).length>0)r=l;else if(typeof process<"u"&&!f)try{let t=o.mode||process.env.NODE_ENV||F,a={};if(e)for(let v of[".env",`.env.${t}`,".env.local",`.env.${t}.local`])a={...a,...e(v,c)};r={...a,...d?process.env:{}}}catch (e2){r={}}u&&!y&&Object.keys(l).length>0?Object.keys(r).length===0?r=l:Object.assign(l,r):u&&Object.keys(r).length>0&&Object.assign(l,r);let h={},E=[];for(let t in i){let a=i[t],v=n&&!t.startsWith(n)?n+t:t,S=a.sourceKey||(r[v]!==void 0?v:r[t]!==void 0?t:v),m=r[S],R={source:r,parsed:h};try{let D=typeof a.required=="function"?a.required(R):a.required;if(m===void 0||m===""&&a.default!==void 0){if(D&&m===void 0)throw new Error("Missing required field");h[t]=a.default}else{let g=a.parse(m,R);if(g!==void 0&&a.metadata){let{min:T,max:V}=a.metadata;if(typeof g=="number"){if(T!==void 0&&g<T)throw new Error(`Below min ${T}`);if(V!==void 0&&g>V)throw new Error(`Above max ${V}`)}}h[t]=g}}catch(D){E.push({key:S,error:D.message,value:m,isSecret:_optionalChain([a, 'access', _2 => _2.metadata, 'optionalAccess', _3 => _3.isSecret])})}}if(E.length>0){if(o.throwOnError){let t=new Error(b(E,!0));throw t.plainMessage=b(E,!1),t}return x||_(E),typeof process<"u"&&process.exit&&!p&&process.exit(1),P(E)}return I(h)}exports.a = F; exports.b = j; exports.c = K; exports.d = C; exports.e = k; exports.f = b; exports.g = _; exports.h = X;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var F="development",j="serve",K="build",C="VITE_DEV_SERVER",k="VITE_";var O=typeof window<"u"&&typeof window.document<"u";function b(i,o=!0){if(O)return`SafeEnv Validation Failed: ${i.map(s=>`${s.key} (${s.error})`).join(", ")}`;let d={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},n=(s,p)=>{let r=String(s),x=()=>r.length+(r.match(/[^\x00-\xff]/g)||[]).length;for(;x()>p;)r=r.slice(0,-1);return r+" ".repeat(p-x())},c=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,u=Math.floor(c*.3),y=Math.floor(c*.5),e=o?d:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},f=`
|
|
2
|
+
${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}
|
|
3
|
+
`;return f+=` ${e.b}${n("Key",u)} \u2502 ${n("Error",y)} \u2502 Value${e.res}
|
|
4
|
+
`,f+=e.d+"\u2500".repeat(c+5)+e.res+`
|
|
5
|
+
`,i.forEach(s=>{let p=s.value===void 0?"undefined":s.isSecret?"********":`"${s.value}"`,r=s.value===void 0?e.d:s.isSecret?e.y:e.cy;f+=` ${e.y}${n(s.key,u)}${e.res} \u2502 ${e.r}${n(s.error,y)}${e.res} \u2502 ${r}${p}${e.res}
|
|
6
|
+
`}),f+=e.d+"\u2500".repeat(c+5)+e.res+`
|
|
7
|
+
`,f+=` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
|
|
8
|
+
`,f}function _(i){if(O){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let o=i.reduce((d,n)=>(d[n.key]={"Error Message":n.error,"Current Value":n.value===void 0?"undefined":n.isSecret?"********":n.value},d),{});console.table(o),console.log("%c \u{1F4A1} Tip: Check your .env files or schema definitions. ","color: #059669; font-style: italic;"),console.groupEnd()}else console.error(b(i,!0))}var l={},$=new WeakMap;function P(i){let o=b(i,!1);return new Proxy({},{get(d,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
|
+
${o}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}var w="[safe-env] Cannot modify read-only environment variables.";function I(i){if($.has(i))return $.get(i);let o=new Proxy(i,{get(d,n){if(n==="__isSafeEnv")return!0;let c=Reflect.get(d,n);return c!==null&&typeof c=="object"&&!Object.isFrozen(c)?I(c):c},set(){throw new Error(w)},deleteProperty(){throw new Error(w)},defineProperty(){throw new Error(w)},setPrototypeOf(){throw new Error(w)}});return $.set(i,o),o}function X(i,o={}){let{loadProcessEnv:d=!0,prefix:n=k,cwd:c,useCache:u=!0,refreshCache:y=!1,envLoader:e}=o;if(y)for(let t in l)delete l[t];let f=typeof window<"u",s=typeof process<"u"&&(!!process.env.VITE||!!process.env[C]),p=f||s||"source"in o,r={},x=!1;if("source"in o)o.source===void 0?(x=!0,r={}):r=o.source;else if(u&&!y&&Object.keys(l).length>0)r=l;else if(typeof process<"u"&&!f)try{let t=o.mode||process.env.NODE_ENV||F,a={};if(e)for(let v of[".env",`.env.${t}`,".env.local",`.env.${t}.local`])a={...a,...e(v,c)};r={...a,...d?process.env:{}}}catch{r={}}u&&!y&&Object.keys(l).length>0?Object.keys(r).length===0?r=l:Object.assign(l,r):u&&Object.keys(r).length>0&&Object.assign(l,r);let h={},E=[];for(let t in i){let a=i[t],v=n&&!t.startsWith(n)?n+t:t,S=a.sourceKey||(r[v]!==void 0?v:r[t]!==void 0?t:v),m=r[S],R={source:r,parsed:h};try{let D=typeof a.required=="function"?a.required(R):a.required;if(m===void 0||m===""&&a.default!==void 0){if(D&&m===void 0)throw new Error("Missing required field");h[t]=a.default}else{let g=a.parse(m,R);if(g!==void 0&&a.metadata){let{min:T,max:V}=a.metadata;if(typeof g=="number"){if(T!==void 0&&g<T)throw new Error(`Below min ${T}`);if(V!==void 0&&g>V)throw new Error(`Above max ${V}`)}}h[t]=g}}catch(D){E.push({key:S,error:D.message,value:m,isSecret:a.metadata?.isSecret})}}if(E.length>0){if(o.throwOnError){let t=new Error(b(E,!0));throw t.plainMessage=b(E,!1),t}return x||_(E),typeof process<"u"&&process.exit&&!p&&process.exit(1),P(E)}return I(h)}export{F as a,j as b,K as c,C as d,k as e,b as f,_ as g,X as h};
|
|
@@ -0,0 +1 @@
|
|
|
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 m(r){let n={},i=r.split(/\r?\n/);for(let d of i){let e=d.trim();if(!e||e.startsWith("#"))continue;let o=e.indexOf("=");if(o===-1)continue;let s=e.slice(0,o).trim(),t=e.slice(o+1).trim();if(!t){n[s]="";continue}let c=t[0];if(c==='"'||c==="'"){let l=t.indexOf(c,1);if(l!==-1){n[s]=t.slice(1,l);continue}}let f=t.indexOf("#");f!==-1&&(t=t.slice(0,f).trim()),n[s]=t}return n}function h(r=".env",n){try{let i=_path2.default.resolve(n||process.cwd(),r);if(_fs2.default.existsSync(i))return m(_fs2.default.readFileSync(i,"utf-8"))}catch (e2){}return{}}exports.a = m; exports.b = h;
|
package/dist/fs-browser.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});function r(n=".env",t){return{}}exports.loadDotEnv = r;
|
package/dist/fs-browser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
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});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkTR6KYAQIcjs = require('./chunk-TR6KYAQI.cjs');exports.loadDotEnv = _chunkTR6KYAQIcjs.b;
|
package/dist/fs-node.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{b as a}from"./chunk-5KPNMU6R.js";export{a as loadDotEnv};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
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 _chunkTR6KYAQIcjs = require('./chunk-TR6KYAQI.cjs');var _chunk6NHVLNFIcjs = require('./chunk-6NHVLNFI.cjs');var o=class{constructor(n,e,r,i=[]){this.type=n,this.default=e,this.required=e===void 0,this.parse=r,this.metadata=i.length?{options:i}:{}}from(n){return this.sourceKey=n,this}optional(){return this.required=!1,this}requiredIf(n){return this.required=n,this}validate(n,e="Custom validation failed"){let r=this.parse;return this.parse=(i,a)=>{let s=r(i,a);if(!n(s,a))throw new Error(e);return s},this}min(n){return this.metadata={...this.metadata,min:n},this}max(n){return this.metadata={...this.metadata,max:n},this}transform(n){let e=this.parse;return this.parse=(r,i)=>n(e(r,i),i),this}secret(){return this.metadata={...this.metadata,isSecret:!0},this}description(n){return this.metadata={...this.metadata,description:n},this}},m= exports.s ={string:t=>new o("string",t,n=>String(n)),number:t=>new o("number",t,n=>{let e=Number(n);if(isNaN(e))throw new Error(`Invalid number: ${n}`);return e}),boolean:t=>new o("boolean",t,n=>{if(typeof n=="boolean")return n;if(n===void 0||n==="")return!1;let e=String(n).toLowerCase().trim();if(["true","1","yes","on"].includes(e))return!0;if(["false","0","no","off"].includes(e))return!1;throw new Error(`Invalid boolean: ${n}`)}),enum:(t,n)=>new o("enum",n,e=>{if(!t.includes(e))throw new Error(`Value "${e}" is not one of: ${t.join(", ")}`);return e},t),array:(t,n=",")=>new o("array",t,e=>Array.isArray(e)?e:typeof e!="string"?[]:e.split(n).map(r=>r.trim()).filter(Boolean))};var b=t=>{try{return new URL(String(t)),!0}catch (e2){return!1}},D= exports.isEmail =t=>/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(String(t)),S= exports.matchesRegex =t=>n=>t.test(String(n)),T= exports.isIPv4 =t=>/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(String(t)),F= exports.isUUID =t=>/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(String(t)),C= exports.isBase64 =t=>/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(String(t)),E= exports.isJSON =t=>{try{return JSON.parse(String(t)),!0}catch (e3){return!1}},N= exports.isHexColor =t=>/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(String(t)),$= exports.isObjectId =t=>/^[0-9a-fA-F]{24}$/.test(String(t)),k= exports.trim =t=>String(t).trim(),v= exports.toLowerCase =t=>String(t).toLowerCase(),I= exports.toUpperCase =t=>String(t).toUpperCase(),O= exports.toJSON =t=>{try{return JSON.parse(String(t))}catch (e4){throw new Error("Invalid JSON string")}};function q(t,n={}){let e=typeof process<"u"&&(_optionalChain([process, 'access', _ => _.release, 'optionalAccess', _2 => _2.name])==="node"||!!_optionalChain([process, 'access', _3 => _3.versions, 'optionalAccess', _4 => _4.node]));return _chunk6NHVLNFIcjs.h.call(void 0, t,{...n,envLoader:e?_chunkTR6KYAQIcjs.b:void 0})}exports.BUILD = _chunk6NHVLNFIcjs.c; exports.DEV = _chunk6NHVLNFIcjs.a; exports.SERVE = _chunk6NHVLNFIcjs.b; exports.VITE_DEV_FLAG = _chunk6NHVLNFIcjs.d; exports.VITE_PREFIX = _chunk6NHVLNFIcjs.e; exports.formatErrorReport = _chunk6NHVLNFIcjs.f; exports.isBase64 = C; exports.isEmail = D; exports.isHexColor = N; exports.isIPv4 = T; exports.isJSON = E; exports.isObjectId = $; exports.isUUID = F; exports.isUrl = b; exports.matchesRegex = S; exports.parseDotEnv = _chunkTR6KYAQIcjs.a; exports.reportErrors = _chunk6NHVLNFIcjs.g; exports.s = m; exports.safeEnv = q; exports.toJSON = O; exports.toLowerCase = v; exports.toUpperCase = I; exports.trim = k;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
3
|
-
|
|
4
|
-
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
|
|
5
|
-
throwOnError?: boolean;
|
|
6
|
-
useCache?: boolean;
|
|
7
|
-
}): Readonly<InferSchema<T>>;
|
|
1
|
+
import { F as FieldDefinition, E as EnvError, S as Schema, a as SafeEnvOptions, I as InferSchema } from './types-BsDPVktI.cjs';
|
|
2
|
+
export { B as BUILD, b as BaseType, D as DEV, c as SERVE, V as VITE_DEV_FLAG, d as VITE_PREFIX, e as ValidationContext } from './types-BsDPVktI.cjs';
|
|
8
3
|
|
|
9
4
|
declare const s: {
|
|
10
5
|
string: (d?: string) => FieldDefinition<string>;
|
|
@@ -14,6 +9,20 @@ declare const s: {
|
|
|
14
9
|
array: (d?: string[], sep?: string) => FieldDefinition<string[]>;
|
|
15
10
|
};
|
|
16
11
|
|
|
12
|
+
declare const isUrl: (v: string) => boolean;
|
|
13
|
+
declare const isEmail: (v: string) => boolean;
|
|
14
|
+
declare const matchesRegex: (pattern: RegExp) => (v: string) => boolean;
|
|
15
|
+
declare const isIPv4: (v: string) => boolean;
|
|
16
|
+
declare const isUUID: (v: string) => boolean;
|
|
17
|
+
declare const isBase64: (v: string) => boolean;
|
|
18
|
+
declare const isJSON: (v: string) => boolean;
|
|
19
|
+
declare const isHexColor: (v: string) => boolean;
|
|
20
|
+
declare const isObjectId: (v: string) => boolean;
|
|
21
|
+
declare const trim: (v: string) => string;
|
|
22
|
+
declare const toLowerCase: (v: string) => string;
|
|
23
|
+
declare const toUpperCase: (v: string) => string;
|
|
24
|
+
declare const toJSON: (v: string) => any;
|
|
25
|
+
|
|
17
26
|
/***
|
|
18
27
|
* 将 .env 内容字符串解析为对象
|
|
19
28
|
* 兼容带引号的值、多层引号内部的注释标识符以及行尾注释
|
|
@@ -23,4 +32,9 @@ declare function parseDotEnv(content: string): Record<string, string>;
|
|
|
23
32
|
declare function formatErrorReport(errors: EnvError[], useColor?: boolean): string;
|
|
24
33
|
declare function reportErrors(errors: EnvError[]): void;
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
|
|
36
|
+
throwOnError?: boolean;
|
|
37
|
+
useCache?: boolean;
|
|
38
|
+
}): Readonly<InferSchema<T>>;
|
|
39
|
+
|
|
40
|
+
export { EnvError, FieldDefinition, InferSchema, SafeEnvOptions, Schema, formatErrorReport, isBase64, isEmail, isHexColor, isIPv4, isJSON, isObjectId, isUUID, isUrl, matchesRegex, parseDotEnv, reportErrors, s, safeEnv, toJSON, toLowerCase, toUpperCase, trim };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
3
|
-
|
|
4
|
-
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
|
|
5
|
-
throwOnError?: boolean;
|
|
6
|
-
useCache?: boolean;
|
|
7
|
-
}): Readonly<InferSchema<T>>;
|
|
1
|
+
import { F as FieldDefinition, E as EnvError, S as Schema, a as SafeEnvOptions, I as InferSchema } from './types-BsDPVktI.js';
|
|
2
|
+
export { B as BUILD, b as BaseType, D as DEV, c as SERVE, V as VITE_DEV_FLAG, d as VITE_PREFIX, e as ValidationContext } from './types-BsDPVktI.js';
|
|
8
3
|
|
|
9
4
|
declare const s: {
|
|
10
5
|
string: (d?: string) => FieldDefinition<string>;
|
|
@@ -14,6 +9,20 @@ declare const s: {
|
|
|
14
9
|
array: (d?: string[], sep?: string) => FieldDefinition<string[]>;
|
|
15
10
|
};
|
|
16
11
|
|
|
12
|
+
declare const isUrl: (v: string) => boolean;
|
|
13
|
+
declare const isEmail: (v: string) => boolean;
|
|
14
|
+
declare const matchesRegex: (pattern: RegExp) => (v: string) => boolean;
|
|
15
|
+
declare const isIPv4: (v: string) => boolean;
|
|
16
|
+
declare const isUUID: (v: string) => boolean;
|
|
17
|
+
declare const isBase64: (v: string) => boolean;
|
|
18
|
+
declare const isJSON: (v: string) => boolean;
|
|
19
|
+
declare const isHexColor: (v: string) => boolean;
|
|
20
|
+
declare const isObjectId: (v: string) => boolean;
|
|
21
|
+
declare const trim: (v: string) => string;
|
|
22
|
+
declare const toLowerCase: (v: string) => string;
|
|
23
|
+
declare const toUpperCase: (v: string) => string;
|
|
24
|
+
declare const toJSON: (v: string) => any;
|
|
25
|
+
|
|
17
26
|
/***
|
|
18
27
|
* 将 .env 内容字符串解析为对象
|
|
19
28
|
* 兼容带引号的值、多层引号内部的注释标识符以及行尾注释
|
|
@@ -23,4 +32,9 @@ declare function parseDotEnv(content: string): Record<string, string>;
|
|
|
23
32
|
declare function formatErrorReport(errors: EnvError[], useColor?: boolean): string;
|
|
24
33
|
declare function reportErrors(errors: EnvError[]): void;
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions & {
|
|
36
|
+
throwOnError?: boolean;
|
|
37
|
+
useCache?: boolean;
|
|
38
|
+
}): Readonly<InferSchema<T>>;
|
|
39
|
+
|
|
40
|
+
export { EnvError, FieldDefinition, InferSchema, SafeEnvOptions, Schema, formatErrorReport, isBase64, isEmail, isHexColor, isIPv4, isJSON, isObjectId, isUUID, isUrl, matchesRegex, parseDotEnv, reportErrors, s, safeEnv, toJSON, toLowerCase, toUpperCase, trim };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as f,b as l}from"./chunk-5KPNMU6R.js";import{a as c,b as g,c as h,d as x,e as w,f as u,g as p,h as d}from"./chunk-JBML47XC.js";var o=class{type;default;required;sourceKey;metadata;parse;constructor(n,e,r,i=[]){this.type=n,this.default=e,this.required=e===void 0,this.parse=r,this.metadata=i.length?{options:i}:{}}from(n){return this.sourceKey=n,this}optional(){return this.required=!1,this}requiredIf(n){return this.required=n,this}validate(n,e="Custom validation failed"){let r=this.parse;return this.parse=(i,a)=>{let s=r(i,a);if(!n(s,a))throw new Error(e);return s},this}min(n){return this.metadata={...this.metadata,min:n},this}max(n){return this.metadata={...this.metadata,max:n},this}transform(n){let e=this.parse;return this.parse=(r,i)=>n(e(r,i),i),this}secret(){return this.metadata={...this.metadata,isSecret:!0},this}description(n){return this.metadata={...this.metadata,description:n},this}},m={string:t=>new o("string",t,n=>String(n)),number:t=>new o("number",t,n=>{let e=Number(n);if(isNaN(e))throw new Error(`Invalid number: ${n}`);return e}),boolean:t=>new o("boolean",t,n=>{if(typeof n=="boolean")return n;if(n===void 0||n==="")return!1;let e=String(n).toLowerCase().trim();if(["true","1","yes","on"].includes(e))return!0;if(["false","0","no","off"].includes(e))return!1;throw new Error(`Invalid boolean: ${n}`)}),enum:(t,n)=>new o("enum",n,e=>{if(!t.includes(e))throw new Error(`Value "${e}" is not one of: ${t.join(", ")}`);return e},t),array:(t,n=",")=>new o("array",t,e=>Array.isArray(e)?e:typeof e!="string"?[]:e.split(n).map(r=>r.trim()).filter(Boolean))};var b=t=>{try{return new URL(String(t)),!0}catch{return!1}},D=t=>/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(String(t)),S=t=>n=>t.test(String(n)),T=t=>/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(String(t)),F=t=>/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(String(t)),C=t=>/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/.test(String(t)),E=t=>{try{return JSON.parse(String(t)),!0}catch{return!1}},N=t=>/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(String(t)),$=t=>/^[0-9a-fA-F]{24}$/.test(String(t)),k=t=>String(t).trim(),v=t=>String(t).toLowerCase(),I=t=>String(t).toUpperCase(),O=t=>{try{return JSON.parse(String(t))}catch{throw new Error("Invalid JSON string")}};function q(t,n={}){let e=typeof process<"u"&&(process.release?.name==="node"||!!process.versions?.node);return d(t,{...n,envLoader:e?l:void 0})}export{h as BUILD,c as DEV,g as SERVE,x as VITE_DEV_FLAG,w as VITE_PREFIX,u as formatErrorReport,C as isBase64,D as isEmail,N as isHexColor,T as isIPv4,E as isJSON,$ as isObjectId,F as isUUID,b as isUrl,S as matchesRegex,f as parseDotEnv,p as reportErrors,m as s,q as safeEnv,O as toJSON,v as toLowerCase,I as toUpperCase,k as trim};
|
|
@@ -4,22 +4,25 @@ declare const BUILD = "build";
|
|
|
4
4
|
declare const VITE_DEV_FLAG = "VITE_DEV_SERVER";
|
|
5
5
|
declare const VITE_PREFIX = "VITE_";
|
|
6
6
|
type BaseType = "string" | "number" | "boolean" | "enum" | "array";
|
|
7
|
+
interface ValidationContext {
|
|
8
|
+
source: Record<string, any>;
|
|
9
|
+
parsed: Record<string, any>;
|
|
10
|
+
}
|
|
7
11
|
interface FieldDefinition<T = any, D extends string = string> {
|
|
8
12
|
type: BaseType;
|
|
9
13
|
default?: T;
|
|
10
|
-
required: boolean;
|
|
14
|
+
required: boolean | ((ctx: ValidationContext) => boolean);
|
|
11
15
|
sourceKey?: string;
|
|
12
16
|
metadata?: any;
|
|
13
|
-
parse: (val: any) => T;
|
|
17
|
+
parse: (val: any, ctx: ValidationContext) => T;
|
|
14
18
|
from: (key: string) => FieldDefinition<T, D>;
|
|
15
|
-
|
|
19
|
+
optional: () => FieldDefinition<T | undefined, D>;
|
|
20
|
+
requiredIf: (fn: (ctx: ValidationContext) => boolean) => FieldDefinition<T, D>;
|
|
21
|
+
validate: (fn: (val: T, ctx: ValidationContext) => boolean, message?: string) => FieldDefinition<T, D>;
|
|
16
22
|
min: (val: number) => FieldDefinition<T, D>;
|
|
17
23
|
max: (val: number) => FieldDefinition<T, D>;
|
|
18
|
-
transform: <U>(fn: (val: T) => U) => FieldDefinition<U, D>;
|
|
24
|
+
transform: <U>(fn: (val: T, ctx: ValidationContext) => U) => FieldDefinition<U, D>;
|
|
19
25
|
secret: () => FieldDefinition<T, D>;
|
|
20
|
-
url: () => FieldDefinition<T, D>;
|
|
21
|
-
email: () => FieldDefinition<T, D>;
|
|
22
|
-
regex: (pattern: RegExp, message?: string) => FieldDefinition<T, D>;
|
|
23
26
|
description: <NewD extends string>(text: NewD) => FieldDefinition<T, NewD>;
|
|
24
27
|
}
|
|
25
28
|
type Schema = Record<string, FieldDefinition<any, any>>;
|
|
@@ -44,4 +47,4 @@ interface SafeEnvOptions {
|
|
|
44
47
|
/** @internal */ devMode?: boolean;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
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 };
|
|
50
|
+
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, type ValidationContext as e };
|
|
@@ -4,22 +4,25 @@ declare const BUILD = "build";
|
|
|
4
4
|
declare const VITE_DEV_FLAG = "VITE_DEV_SERVER";
|
|
5
5
|
declare const VITE_PREFIX = "VITE_";
|
|
6
6
|
type BaseType = "string" | "number" | "boolean" | "enum" | "array";
|
|
7
|
+
interface ValidationContext {
|
|
8
|
+
source: Record<string, any>;
|
|
9
|
+
parsed: Record<string, any>;
|
|
10
|
+
}
|
|
7
11
|
interface FieldDefinition<T = any, D extends string = string> {
|
|
8
12
|
type: BaseType;
|
|
9
13
|
default?: T;
|
|
10
|
-
required: boolean;
|
|
14
|
+
required: boolean | ((ctx: ValidationContext) => boolean);
|
|
11
15
|
sourceKey?: string;
|
|
12
16
|
metadata?: any;
|
|
13
|
-
parse: (val: any) => T;
|
|
17
|
+
parse: (val: any, ctx: ValidationContext) => T;
|
|
14
18
|
from: (key: string) => FieldDefinition<T, D>;
|
|
15
|
-
|
|
19
|
+
optional: () => FieldDefinition<T | undefined, D>;
|
|
20
|
+
requiredIf: (fn: (ctx: ValidationContext) => boolean) => FieldDefinition<T, D>;
|
|
21
|
+
validate: (fn: (val: T, ctx: ValidationContext) => boolean, message?: string) => FieldDefinition<T, D>;
|
|
16
22
|
min: (val: number) => FieldDefinition<T, D>;
|
|
17
23
|
max: (val: number) => FieldDefinition<T, D>;
|
|
18
|
-
transform: <U>(fn: (val: T) => U) => FieldDefinition<U, D>;
|
|
24
|
+
transform: <U>(fn: (val: T, ctx: ValidationContext) => U) => FieldDefinition<U, D>;
|
|
19
25
|
secret: () => FieldDefinition<T, D>;
|
|
20
|
-
url: () => FieldDefinition<T, D>;
|
|
21
|
-
email: () => FieldDefinition<T, D>;
|
|
22
|
-
regex: (pattern: RegExp, message?: string) => FieldDefinition<T, D>;
|
|
23
26
|
description: <NewD extends string>(text: NewD) => FieldDefinition<T, NewD>;
|
|
24
27
|
}
|
|
25
28
|
type Schema = Record<string, FieldDefinition<any, any>>;
|
|
@@ -44,4 +47,4 @@ interface SafeEnvOptions {
|
|
|
44
47
|
/** @internal */ devMode?: boolean;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
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 };
|
|
50
|
+
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, type ValidationContext as e };
|
package/dist/vite.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk6NHVLNFIcjs = require('./chunk-6NHVLNFI.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===_chunk6NHVLNFIcjs.b,process.env[_chunk6NHVLNFIcjs.d]=o?"true":"";let{envDir:t=e.root,prefix:r=e.envPrefix||_chunk6NHVLNFIcjs.e}=f,p=_vite.loadEnv.call(void 0, e.mode,t,r);try{_chunk6NHVLNFIcjs.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
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
package/dist/vite.d.ts
CHANGED
package/dist/vite.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{b as a,d as i,e as l,h as m}from"./chunk-
|
|
1
|
+
import{b as a,d as i,e as l,h as m}from"./chunk-JBML47XC.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
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
package/dist/chunk-7CVG4I6F.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function u(f){let t={},l=f.split(/\r?\n/);for(let d of l){let i=d.trim();if(!i||i.startsWith("#"))continue;let e=i.indexOf("=");if(e===-1)continue;let s=i.slice(0,e).trim(),n=i.slice(e+1).trim();if(!n){t[s]="";continue}let o=n[0];if(o==='"'||o==="'"){let r=n.indexOf(o,1);if(r!==-1){t[s]=n.slice(1,r);continue}}let c=n.indexOf("#");c!==-1&&(n=n.slice(0,c).trim()),t[s]=n}return t}export{u as a};
|
package/dist/chunk-D6WM53FN.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
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;
|
package/dist/chunk-I7AUKTXE.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
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};
|
package/dist/chunk-K2JQKLKN.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{a as _}from"./chunk-I7AUKTXE.js";var S="development",P="serve",C="build",F="VITE_DEV_SERVER",V="VITE_";var R=typeof window<"u"&&typeof window.document<"u";function x(o,t=!0){if(R)return`SafeEnv Validation Failed: ${o.map(i=>`${i.key} (${i.error})`).join(", ")}`;let d={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},r=(i,s)=>{let c=String(i),l=()=>c.length+(c.match(/[^\x00-\xff]/g)||[]).length;for(;l()>s;)c=c.slice(0,-1);return c+" ".repeat(s-l())},a=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,v=Math.floor(a*.3),m=Math.floor(a*.5),e=t?d:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},u=`
|
|
2
|
-
${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}
|
|
3
|
-
`;return u+=` ${e.b}${r("Key",v)} \u2502 ${r("Error",m)} \u2502 Value${e.res}
|
|
4
|
-
`,u+=e.d+"\u2500".repeat(a+5)+e.res+`
|
|
5
|
-
`,o.forEach(i=>{let s=i.value===void 0?"undefined":i.isSecret?"********":`"${i.value}"`,c=i.value===void 0?e.d:i.isSecret?e.y:e.cy;u+=` ${e.y}${r(i.key,v)}${e.res} \u2502 ${e.r}${r(i.error,m)}${e.res} \u2502 ${c}${s}${e.res}
|
|
6
|
-
`}),u+=e.d+"\u2500".repeat(a+5)+e.res+`
|
|
7
|
-
`,u+=` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
|
|
8
|
-
`,u}function k(o){if(R){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let t=o.reduce((d,r)=>(d[r.key]={"Error Message":r.error,"Current Value":r.value===void 0?"undefined":r.isSecret?"********":r.value},d),{});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(x(o,!0))}var p={},$=new WeakMap;function I(o){let t=x(o,!1);return new Proxy({},{get(d,r){if(r==="__isSafeEnvError")return!0;if(r==="toJSON")return()=>({error:"SafeEnv Validation Failed"});throw new Error(`[safe-env] Cannot access "${String(r)}" because validation failed:
|
|
9
|
-
${t}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}var b="[safe-env] Cannot modify read-only environment variables.";function O(o){if($.has(o))return $.get(o);let t=new Proxy(o,{get(d,r){if(r==="__isSafeEnv")return!0;let a=Reflect.get(d,r);return a!==null&&typeof a=="object"&&!Object.isFrozen(a)?O(a):a},set(){throw new Error(b)},deleteProperty(){throw new Error(b)},defineProperty(){throw new Error(b)},setPrototypeOf(){throw new Error(b)}});return $.set(o,t),t}function L(o,t={}){let{loadProcessEnv:d=!0,prefix:r=V,cwd:a,useCache:v=!0,refreshCache:m=!1}=t;if(m)for(let n in p)delete p[n];let e=typeof window<"u",u=typeof process<"u"&&(!!process.env.VITE||!!process.env[F]),i=e||u||"source"in t,s={};if("source"in t)s=t.source||{};else if(v&&!m&&Object.keys(p).length>0)s=p;else if(typeof process<"u"&&!e)try{let n=t.mode||process.env.NODE_ENV||S,{loadDotEnv:f}=_("./fs-node.cjs"),E={};for(let h of[".env",`.env.${n}`,".env.local",`.env.${n}.local`])E={...E,...f(h,a)};s={...E,...d?process.env:{}}}catch{s={}}if(v&&Object.keys(s).length>0&&Object.keys(p).length===0&&Object.assign(p,s),i&&Object.keys(s).length===0)return{};let c={},l=[];for(let n in o){let f=o[n],E=r&&!n.startsWith(r)?r+n:n,h=f.sourceKey||(s[E]!==void 0?E:s[n]!==void 0?n:E),g=s[h];try{if(g===void 0||g===""&&f.default!==void 0){if(f.required&&g===void 0)throw new Error("Missing required field");c[n]=f.default}else{let y=f.parse(g);if(y!==void 0&&f.metadata){let{min:w,max:D,validate:T}=f.metadata;if(typeof y=="number"){if(w!==void 0&&y<w)throw new Error(`Below min ${w}`);if(D!==void 0&&y>D)throw new Error(`Above max ${D}`)}if(T&&!T.fn(y))throw new Error(T.message)}c[n]=y}}catch(y){l.push({key:h,error:y.message,value:g,isSecret:f.metadata?.isSecret})}}if(l.length>0){if(t.throwOnError){let n=new Error(x(l,!0));throw n.plainMessage=x(l,!1),n}return k(l),typeof process<"u"&&process.exit&&!i&&process.exit(1),I(l)}return O(c)}export{S as a,P as b,C as c,F as d,V as e,x as f,k as g,L as h};
|
package/dist/chunk-PBYVLIUG.cjs
DELETED
|
@@ -1,9 +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 _chunkD6WM53FNcjs = require('./chunk-D6WM53FN.cjs');var S="development",P= exports.b ="serve",C= exports.c ="build",F= exports.d ="VITE_DEV_SERVER",V= exports.e ="VITE_";var R=typeof window<"u"&&typeof window.document<"u";function x(o,t=!0){if(R)return`SafeEnv Validation Failed: ${o.map(i=>`${i.key} (${i.error})`).join(", ")}`;let d={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m",cy:"\x1B[36m"},r=(i,s)=>{let c=String(i),l=()=>c.length+(c.match(/[^\x00-\xff]/g)||[]).length;for(;l()>s;)c=c.slice(0,-1);return c+" ".repeat(s-l())},a=Math.max(80,(typeof process<"u"?process.stdout.columns:80)||80)-10,v=Math.floor(a*.3),m=Math.floor(a*.5),e=t?d:{r:"",g:"",y:"",b:"",res:"",d:"",cy:""},u=`
|
|
2
|
-
${e.r}${e.b}\u274C SafeEnv Validation Failed${e.res}
|
|
3
|
-
`;return u+=` ${e.b}${r("Key",v)} \u2502 ${r("Error",m)} \u2502 Value${e.res}
|
|
4
|
-
`,u+=e.d+"\u2500".repeat(a+5)+e.res+`
|
|
5
|
-
`,o.forEach(i=>{let s=i.value===void 0?"undefined":i.isSecret?"********":`"${i.value}"`,c=i.value===void 0?e.d:i.isSecret?e.y:e.cy;u+=` ${e.y}${r(i.key,v)}${e.res} \u2502 ${e.r}${r(i.error,m)}${e.res} \u2502 ${c}${s}${e.res}
|
|
6
|
-
`}),u+=e.d+"\u2500".repeat(a+5)+e.res+`
|
|
7
|
-
`,u+=` ${e.g}\u{1F4A1} Tip: Check your .env files or schema definitions.${e.res}
|
|
8
|
-
`,u}function k(o){if(R){console.group("%c \u274C SafeEnv Validation Failed ","background: #fee2e2; color: #b91c1c; font-weight: bold; padding: 4px; border-radius: 2px;");let t=o.reduce((d,r)=>(d[r.key]={"Error Message":r.error,"Current Value":r.value===void 0?"undefined":r.isSecret?"********":r.value},d),{});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(x(o,!0))}var p={},$=new WeakMap;function I(o){let t=x(o,!1);return new Proxy({},{get(d,r){if(r==="__isSafeEnvError")return!0;if(r==="toJSON")return()=>({error:"SafeEnv Validation Failed"});throw new Error(`[safe-env] Cannot access "${String(r)}" because validation failed:
|
|
9
|
-
${t}`)},ownKeys(){return[]},getOwnPropertyDescriptor(){}})}var b="[safe-env] Cannot modify read-only environment variables.";function O(o){if($.has(o))return $.get(o);let t=new Proxy(o,{get(d,r){if(r==="__isSafeEnv")return!0;let a=Reflect.get(d,r);return a!==null&&typeof a=="object"&&!Object.isFrozen(a)?O(a):a},set(){throw new Error(b)},deleteProperty(){throw new Error(b)},defineProperty(){throw new Error(b)},setPrototypeOf(){throw new Error(b)}});return $.set(o,t),t}function L(o,t={}){let{loadProcessEnv:d=!0,prefix:r=V,cwd:a,useCache:v=!0,refreshCache:m=!1}=t;if(m)for(let n in p)delete p[n];let e=typeof window<"u",u=typeof process<"u"&&(!!process.env.VITE||!!process.env[F]),i=e||u||"source"in t,s={};if("source"in t)s=t.source||{};else if(v&&!m&&Object.keys(p).length>0)s=p;else if(typeof process<"u"&&!e)try{let n=t.mode||process.env.NODE_ENV||S,{loadDotEnv:f}=_chunkD6WM53FNcjs.a.call(void 0, "./fs-node.cjs"),E={};for(let h of[".env",`.env.${n}`,".env.local",`.env.${n}.local`])E={...E,...f(h,a)};s={...E,...d?process.env:{}}}catch (e2){s={}}if(v&&Object.keys(s).length>0&&Object.keys(p).length===0&&Object.assign(p,s),i&&Object.keys(s).length===0)return{};let c={},l=[];for(let n in o){let f=o[n],E=r&&!n.startsWith(r)?r+n:n,h=f.sourceKey||(s[E]!==void 0?E:s[n]!==void 0?n:E),g=s[h];try{if(g===void 0||g===""&&f.default!==void 0){if(f.required&&g===void 0)throw new Error("Missing required field");c[n]=f.default}else{let y=f.parse(g);if(y!==void 0&&f.metadata){let{min:w,max:D,validate:T}=f.metadata;if(typeof y=="number"){if(w!==void 0&&y<w)throw new Error(`Below min ${w}`);if(D!==void 0&&y>D)throw new Error(`Above max ${D}`)}if(T&&!T.fn(y))throw new Error(T.message)}c[n]=y}}catch(y){l.push({key:h,error:y.message,value:g,isSecret:_optionalChain([f, 'access', _2 => _2.metadata, 'optionalAccess', _3 => _3.isSecret])})}}if(l.length>0){if(t.throwOnError){let n=new Error(x(l,!0));throw n.plainMessage=x(l,!1),n}return k(l),typeof process<"u"&&process.exit&&!i&&process.exit(1),I(l)}return O(c)}exports.a = S; exports.b = P; exports.c = C; exports.d = F; exports.e = V; exports.f = x; exports.g = k; exports.h = L;
|
package/dist/chunk-PLO26PP5.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});function u(f){let t={},l=f.split(/\r?\n/);for(let d of l){let i=d.trim();if(!i||i.startsWith("#"))continue;let e=i.indexOf("=");if(e===-1)continue;let s=i.slice(0,e).trim(),n=i.slice(e+1).trim();if(!n){t[s]="";continue}let o=n[0];if(o==='"'||o==="'"){let r=n.indexOf(o,1);if(r!==-1){t[s]=n.slice(1,r);continue}}let c=n.indexOf("#");c!==-1&&(n=n.slice(0,c).trim()),t[s]=n}return t}exports.a = u;
|