@zh-moody/safe-env 0.3.3 → 0.3.4
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 +148 -0
- package/README.md +39 -56
- package/dist/{chunk-FH2DFX4J.cjs → chunk-MODJPD2X.cjs} +1 -1
- package/dist/chunk-UONNQTFU.js +3 -0
- package/dist/chunk-WXZ32K3G.cjs +3 -0
- package/dist/chunk-WZTPUQ3S.js +1 -0
- package/dist/fs-browser.cjs +1 -1
- package/dist/fs-browser.d.cts +1 -1
- package/dist/fs-browser.d.ts +1 -1
- package/dist/fs-browser.js +1 -1
- package/dist/fs-node.cjs +1 -1
- package/dist/fs-node.d.cts +1 -1
- package/dist/fs-node.d.ts +1 -1
- package/dist/fs-node.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1
- package/dist/{types-B59cqDDx.d.cts → types-CFipqnoe.d.cts} +3 -0
- package/dist/{types-B59cqDDx.d.ts → types-CFipqnoe.d.ts} +3 -0
- 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-GCSZ35F2.cjs +0 -5
- package/dist/chunk-NRXIL5NF.js +0 -5
- package/dist/chunk-POVTEBYN.js +0 -1
package/README.en.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @zh-moody/safe-env 🛡️
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@zh-moody/safe-env)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://github.com/zhMoody/safe-env)
|
|
6
|
+
|
|
7
|
+
[简体中文](./README.md) | English
|
|
8
|
+
|
|
9
|
+
**Say goodbye to `undefined`! Intercept all configuration risks at the first line of your app.**
|
|
10
|
+
|
|
11
|
+
Whether you are writing Vue, React, or Node.js, environment variables are often a source of production incidents. `safe-env` ensures your app always runs on the expected configuration through strong-typed Schema validation and runtime protection.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### 🚀 Core Features
|
|
16
|
+
|
|
17
|
+
- **Build-time Validation**: Provides a Vite plugin to intercept invalid configurations during development or build.
|
|
18
|
+
- **Sensitive Data Masking**: Supports `.secret()` to ensure keys and passwords are masked as `********` in logs or error tables.
|
|
19
|
+
- **Runtime Immutability**: Parsed config objects are deep-frozen with `Object.freeze` by default, preventing any illegal runtime modification.
|
|
20
|
+
- **Monorepo Ready**: Supports `cwd` parameter to explicitly specify the `.env` directory, ideal for complex project architectures.
|
|
21
|
+
- **IDE Enhancement**: Supports `.description()` to view variable usage and documentation directly via hover in your code.
|
|
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
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
### 📦 Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @zh-moody/safe-env
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### 🚀 Quick Start
|
|
36
|
+
|
|
37
|
+
#### 🔹 [Vite / React / Vue]
|
|
38
|
+
For frontend projects, use the Vite plugin for **build-time validation**.
|
|
39
|
+
|
|
40
|
+
**1. Configure Vite Plugin (`vite.config.ts`):**
|
|
41
|
+
```typescript
|
|
42
|
+
import { viteSafeEnv } from '@zh-moody/safe-env/vite';
|
|
43
|
+
import { schema } from './src/env';
|
|
44
|
+
|
|
45
|
+
export default {
|
|
46
|
+
plugins: [
|
|
47
|
+
viteSafeEnv(schema)
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**2. Define and Export Config (`src/env.ts`):**
|
|
53
|
+
```typescript
|
|
54
|
+
import { safeEnv, s } from '@zh-moody/safe-env';
|
|
55
|
+
|
|
56
|
+
export const schema = {
|
|
57
|
+
VITE_API_URL: s.string().url().description("Backend API Base URL"),
|
|
58
|
+
VITE_PORT: s.number(3000).description("Development Server Port"),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const env = safeEnv(schema, {
|
|
62
|
+
source: import.meta.env
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> **💡 Best Practice: Prevent Vite Type Pollution**
|
|
67
|
+
> To completely disable the insecure original `import.meta.env.XXX` hints, modify `src/vite-env.d.ts`:
|
|
68
|
+
> ```typescript
|
|
69
|
+
> interface ImportMetaEnv {
|
|
70
|
+
> [key: string]: never;
|
|
71
|
+
> }
|
|
72
|
+
> ```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
#### 🔸 [Node.js / Server-side]
|
|
77
|
+
In Node.js, the library automatically looks for and parses `.env` files on disk.
|
|
78
|
+
|
|
79
|
+
**1. Define Config (`src/config.ts`):**
|
|
80
|
+
```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
|
+
});
|
|
90
|
+
|
|
91
|
+
export default config;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### 🛠️ API Reference
|
|
97
|
+
|
|
98
|
+
#### 1. Define Fields (`s.xxx`)
|
|
99
|
+
- `s.string(default?)`: String field. Required if no default value.
|
|
100
|
+
- `s.number(default?)`: Automatically converted to `number` and validated.
|
|
101
|
+
- `s.boolean(default?)`: Supports `"true"`, `"1"`, `"yes"`, `"on"` as `true`.
|
|
102
|
+
- `s.array(default?, separator?)`: Splits string by separator (default `,`) into an array.
|
|
103
|
+
- `s.enum(options, default?)`: Value must be one of the provided options.
|
|
104
|
+
|
|
105
|
+
#### 2. Validation & Enhancement (Chainable)
|
|
106
|
+
|
|
107
|
+
- **`.secret()`**: Masks the value as `********` in error reports.
|
|
108
|
+
```typescript
|
|
109
|
+
PASSWORD: s.string().secret()
|
|
110
|
+
```
|
|
111
|
+
- **`.url()` / `.email()`**: Built-in format validation.
|
|
112
|
+
```typescript
|
|
113
|
+
API_URL: s.string().url()
|
|
114
|
+
```
|
|
115
|
+
- **`.regex(pattern, msg?)`**: Custom regex validation.
|
|
116
|
+
```typescript
|
|
117
|
+
VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "Invalid format")
|
|
118
|
+
```
|
|
119
|
+
- **`.description(text)`**: Adds a description for IDE hover hints.
|
|
120
|
+
```typescript
|
|
121
|
+
PORT: s.number(3000).description("Server Port")
|
|
122
|
+
```
|
|
123
|
+
- **`.transform(fn)`**: Custom data transformation, supports multi-level piping.
|
|
124
|
+
```typescript
|
|
125
|
+
NAME: s.string().transform(v => v.trim()).transform(v => v.toUpperCase())
|
|
126
|
+
```
|
|
127
|
+
- **`.from(key)`**: Maps environment variable name (Alias).
|
|
128
|
+
```typescript
|
|
129
|
+
port: s.number().from('VITE_SERVER_PORT')
|
|
130
|
+
```
|
|
131
|
+
- **`.min(n)` / `.max(n)`**: Constraints for number values.
|
|
132
|
+
```typescript
|
|
133
|
+
PORT: s.number().min(1024).max(65535)
|
|
134
|
+
```
|
|
135
|
+
- **`.validate(fn, msg?)`**: Fully custom validation logic.
|
|
136
|
+
```typescript
|
|
137
|
+
INTERNAL_URL: s.string().validate(v => v.endsWith('.internal.com'), 'Must be internal')
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 🎨 Error Reporting
|
|
143
|
+
When validation fails, `safe-env` outputs a structured, adaptive table in the console showing: **Key / Error Reason / Current Value (Masked)**.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### 📄 License
|
|
148
|
+
[MIT License](./LICENSE) - Copyright (c) 2026 Moody.
|
package/README.md
CHANGED
|
@@ -4,19 +4,22 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://github.com/zhMoody/safe-env)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
简体中文 | [English](./README.en.md)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**告别 `undefined`!在应用启动的第一行,拦截所有配置隐患。**
|
|
10
|
+
|
|
11
|
+
无论你在写 Vue、React 还是 Node.js,环境变量配置永远是生产事故的高发区。`safe-env` 通过强类型 Schema 校验与运行时保护,确保你的应用始终运行在预期的配置之上。
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
13
15
|
### 🚀 核心特性
|
|
14
16
|
|
|
15
|
-
- **构建时预校验**:提供 Vite
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
17
|
+
- **构建时预校验**:提供 Vite 插件,在开发启动或打包瞬间拦截非法配置。
|
|
18
|
+
- **敏感数据脱敏**:支持 `.secret()` 标记,确保密钥等敏感信息不会泄露在日志或报错表格中。
|
|
19
|
+
- **运行时深度冻结**:解析后的配置对象默认开启 `Object.freeze`,杜绝任何运行时的非法篡改。
|
|
20
|
+
- **Monorepo 精准定位**:支持 `cwd` 参数,可显式指定配置文件检索目录,适配复杂的项目架构。
|
|
21
|
+
- **IDE 增强**:支持 `.description()`,在代码中通过悬停直接查看变量用途与文档。
|
|
22
|
+
- **严谨的类型解析**:内置 `s.array()`, `s.boolean()` 增强转换,支持 `.transform()` 链式 Pipe 处理。
|
|
20
23
|
- **极致轻量**:Gzip 压缩后仅 **1.9 KB**,零运行时依赖。
|
|
21
24
|
|
|
22
25
|
---
|
|
@@ -25,21 +28,6 @@
|
|
|
25
28
|
|
|
26
29
|
```bash
|
|
27
30
|
npm install @zh-moody/safe-env
|
|
28
|
-
# 或者
|
|
29
|
-
pnpm add @zh-moody/safe-env
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
### 🛠️ 准备工作 (Prerequisites)
|
|
35
|
-
|
|
36
|
-
在项目根目录下创建一个 `.env` 文件(这是本库解析数据的来源):
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# .env 示例
|
|
40
|
-
VITE_API_URL=https://api.com
|
|
41
|
-
VITE_PORT=3000
|
|
42
|
-
VITE_FEATURES=auth,storage
|
|
43
31
|
```
|
|
44
32
|
|
|
45
33
|
---
|
|
@@ -52,11 +40,11 @@ VITE_FEATURES=auth,storage
|
|
|
52
40
|
**1. 配置 Vite 插件 (`vite.config.ts`):**
|
|
53
41
|
```typescript
|
|
54
42
|
import { viteSafeEnv } from '@zh-moody/safe-env/vite';
|
|
55
|
-
import { schema } from './src/env';
|
|
43
|
+
import { schema } from './src/env';
|
|
56
44
|
|
|
57
45
|
export default {
|
|
58
46
|
plugins: [
|
|
59
|
-
viteSafeEnv(schema)
|
|
47
|
+
viteSafeEnv(schema)
|
|
60
48
|
]
|
|
61
49
|
}
|
|
62
50
|
```
|
|
@@ -68,7 +56,6 @@ import { safeEnv, s } from '@zh-moody/safe-env';
|
|
|
68
56
|
export const schema = {
|
|
69
57
|
VITE_API_URL: s.string().url().description("后端 API 地址"),
|
|
70
58
|
VITE_PORT: s.number(3000).description("服务端口"),
|
|
71
|
-
VITE_FEATURES: s.array().description("启用的特性列表")
|
|
72
59
|
};
|
|
73
60
|
|
|
74
61
|
export const env = safeEnv(schema, {
|
|
@@ -76,19 +63,29 @@ export const env = safeEnv(schema, {
|
|
|
76
63
|
});
|
|
77
64
|
```
|
|
78
65
|
|
|
66
|
+
> **💡 最佳实践:防止 Vite 类型污染**
|
|
67
|
+
> 为彻底禁用 `import.meta.env.XXX` 的原生提示,建议修改 `src/vite-env.d.ts`:
|
|
68
|
+
> ```typescript
|
|
69
|
+
> interface ImportMetaEnv {
|
|
70
|
+
> [key: string]: never;
|
|
71
|
+
> }
|
|
72
|
+
> ```
|
|
73
|
+
|
|
79
74
|
---
|
|
80
75
|
|
|
81
76
|
#### 🔸 [Node.js / 服务端] 使用
|
|
82
|
-
|
|
77
|
+
在后端环境,库会自动检索并解析磁盘上的 `.env` 系列文件。
|
|
83
78
|
|
|
84
79
|
**1. 定义配置 (`src/config.ts`):**
|
|
85
80
|
```typescript
|
|
86
81
|
import { safeEnv, s } from '@zh-moody/safe-env';
|
|
87
82
|
|
|
88
83
|
const config = safeEnv({
|
|
89
|
-
|
|
84
|
+
DB_PASSWORD: s.string().secret().description("数据库密码"),
|
|
90
85
|
DB_PORT: s.number(5432).min(1).max(65535),
|
|
91
|
-
|
|
86
|
+
}, {
|
|
87
|
+
// 在 Monorepo 或特定部署环境下,可显式指定 .env 所在目录
|
|
88
|
+
// cwd: '/path/to/project-root'
|
|
92
89
|
});
|
|
93
90
|
|
|
94
91
|
export default config;
|
|
@@ -100,66 +97,52 @@ export default config;
|
|
|
100
97
|
|
|
101
98
|
#### 1. 定义字段 (`s.xxx`)
|
|
102
99
|
- `s.string(default?)`: 字符串。若无默认值则必填。
|
|
103
|
-
- `s.number(default?)`:
|
|
104
|
-
- `s.boolean(default?)`: 布尔型。支持将 `"true"`, `"1"`, `"yes"`, `"on"` 解析为 `true
|
|
100
|
+
- `s.number(default?)`: 数字。自动转换为 `number` 类型并校验合法性。
|
|
101
|
+
- `s.boolean(default?)`: 布尔型。支持将 `"true"`, `"1"`, `"yes"`, `"on"` 解析为 `true`。
|
|
105
102
|
- `s.array(default?, separator?)`: 数组型。支持将字符串按分隔符(默认 `,`)拆分为数组。
|
|
106
|
-
- `s.enum(options, default?)`:
|
|
103
|
+
- `s.enum(options, default?)`: 枚举。值必须在预设数组中。
|
|
107
104
|
|
|
108
105
|
#### 2. 校验与增强 (链式调用)
|
|
109
106
|
|
|
110
107
|
每个字段都可以通过链式调用进行深度定制:
|
|
111
108
|
|
|
112
|
-
- **`.
|
|
109
|
+
- **`.secret()`**: 标记敏感数据,报错时该值会以 `********` 遮罩显示。
|
|
113
110
|
```typescript
|
|
114
|
-
|
|
111
|
+
PASSWORD: s.string().secret()
|
|
115
112
|
```
|
|
116
|
-
- **`.email()`**:
|
|
113
|
+
- **`.url()` / `.email()`**: 常用格式校验。
|
|
117
114
|
```typescript
|
|
118
|
-
|
|
115
|
+
API_URL: s.string().url()
|
|
119
116
|
```
|
|
120
117
|
- **`.regex(pattern, msg?)`**: 自定义正则校验。
|
|
121
118
|
```typescript
|
|
122
|
-
VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "
|
|
119
|
+
VERSION: s.string().regex(/^v\d+\.\d+\.\d+$/, "格式错误")
|
|
123
120
|
```
|
|
124
|
-
- **`.description(text)`**:
|
|
121
|
+
- **`.description(text)`**: 添加变量描述,映射到 IDE 悬停提示中。
|
|
125
122
|
```typescript
|
|
126
|
-
PORT: s.number(3000).description("
|
|
123
|
+
PORT: s.number(3000).description("服务端口")
|
|
127
124
|
```
|
|
128
|
-
- **`.transform(fn)`**:
|
|
125
|
+
- **`.transform(fn)`**: 自定义数据转换,支持多级 Pipe。
|
|
129
126
|
```typescript
|
|
130
|
-
// 示例 1: 拿到字符串 -> 去空格 -> 转大写
|
|
131
127
|
NAME: s.string().transform(v => v.trim()).transform(v => v.toUpperCase())
|
|
132
|
-
|
|
133
|
-
// 示例 2: 将逗号分隔的数字字符串转为数字数组
|
|
134
|
-
SCORES: s.array().transform(arr => arr.map(Number))
|
|
135
128
|
```
|
|
136
129
|
- **`.from(key)`**: 映射环境变量名(别名)。
|
|
137
130
|
```typescript
|
|
138
|
-
// 即使环境变量叫 VITE_SERVER_PORT,代码里也可以叫 port
|
|
139
131
|
port: s.number().from('VITE_SERVER_PORT')
|
|
140
132
|
```
|
|
141
133
|
- **`.min(n)` / `.max(n)`**: 限制数字取值范围。
|
|
142
134
|
```typescript
|
|
143
|
-
// 端口必须在 1024-65535 之间
|
|
144
135
|
PORT: s.number().min(1024).max(65535)
|
|
145
136
|
```
|
|
146
|
-
- **`.validate(fn, msg?)`**:
|
|
137
|
+
- **`.validate(fn, msg?)`**: 完全自定义的逻辑校验。
|
|
147
138
|
```typescript
|
|
148
|
-
|
|
149
|
-
INTERNAL_URL: s.string().validate(v => v.endsWith('.internal.com'), 'Must be an internal URL')
|
|
139
|
+
INTERNAL_URL: s.string().validate(v => v.endsWith('.internal.com'), 'Must be internal')
|
|
150
140
|
```
|
|
151
141
|
|
|
152
|
-
#### 3. 加载规则 (Env Priority)
|
|
153
|
-
`safe-env` 遵循标准的优先级顺序(从低到高):
|
|
154
|
-
1. `.env` (基础配置)
|
|
155
|
-
2. `.env.[mode]` (环境配置,如 `.env.development`)
|
|
156
|
-
3. `.env.local` (本地覆盖)
|
|
157
|
-
4. `.env.[mode].local` (环境特定的本地覆盖)
|
|
158
|
-
|
|
159
142
|
---
|
|
160
143
|
|
|
161
144
|
### 🎨 错误报告
|
|
162
|
-
当校验失败时,`safe-env`
|
|
145
|
+
当校验失败时,`safe-env` 会在控制台输出结构化的自适应表格,清晰展示:**Key / 错误原因 / 当前值(已脱敏)**。
|
|
163
146
|
|
|
164
147
|
---
|
|
165
148
|
|
|
@@ -1 +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 s
|
|
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;
|
|
@@ -0,0 +1,3 @@
|
|
|
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};
|
|
@@ -0,0 +1,3 @@
|
|
|
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;
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
package/dist/fs-browser.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});function
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});function r(n=".env",t){return{}}exports.loadDotEnv = r;
|
package/dist/fs-browser.d.cts
CHANGED
package/dist/fs-browser.d.ts
CHANGED
package/dist/fs-browser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
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});var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkMODJPD2Xcjs = require('./chunk-MODJPD2X.cjs');exports.loadDotEnv = _chunkMODJPD2Xcjs.b;
|
package/dist/fs-node.d.cts
CHANGED
package/dist/fs-node.d.ts
CHANGED
package/dist/fs-node.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as a}from"./chunk-
|
|
1
|
+
import{b as a}from"./chunk-WZTPUQ3S.js";export{a as loadDotEnv};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var
|
|
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;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FieldDefinition, S as Schema, I as InferSchema, E as EnvError } from './types-
|
|
2
|
-
export { B as BaseType } from './types-
|
|
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';
|
|
3
3
|
|
|
4
4
|
declare const s: {
|
|
5
5
|
string: (defaultValue?: string) => FieldDefinition<string>;
|
|
@@ -14,8 +14,9 @@ interface SafeEnvOptions {
|
|
|
14
14
|
loadProcessEnv?: boolean;
|
|
15
15
|
source?: Record<string, any>;
|
|
16
16
|
prefix?: string;
|
|
17
|
+
cwd?: string;
|
|
17
18
|
}
|
|
18
|
-
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): InferSchema<T
|
|
19
|
+
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): Readonly<InferSchema<T>>;
|
|
19
20
|
|
|
20
21
|
/***
|
|
21
22
|
* 将 .env 内容字符串解析为对象
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FieldDefinition, S as Schema, I as InferSchema, E as EnvError } from './types-
|
|
2
|
-
export { B as BaseType } from './types-
|
|
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';
|
|
3
3
|
|
|
4
4
|
declare const s: {
|
|
5
5
|
string: (defaultValue?: string) => FieldDefinition<string>;
|
|
@@ -14,8 +14,9 @@ interface SafeEnvOptions {
|
|
|
14
14
|
loadProcessEnv?: boolean;
|
|
15
15
|
source?: Record<string, any>;
|
|
16
16
|
prefix?: string;
|
|
17
|
+
cwd?: string;
|
|
17
18
|
}
|
|
18
|
-
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): InferSchema<T
|
|
19
|
+
declare function safeEnv<T extends Schema>(schema: T, options?: SafeEnvOptions): Readonly<InferSchema<T>>;
|
|
19
20
|
|
|
20
21
|
/***
|
|
21
22
|
* 将 .env 内容字符串解析为对象
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as
|
|
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};
|
|
@@ -9,6 +9,7 @@ interface FieldDefinition<T = any, D extends string = string> {
|
|
|
9
9
|
max?: number;
|
|
10
10
|
options?: T[];
|
|
11
11
|
description?: string;
|
|
12
|
+
isSecret?: boolean;
|
|
12
13
|
validate?: {
|
|
13
14
|
fn: (val: T) => boolean;
|
|
14
15
|
message: string;
|
|
@@ -20,6 +21,7 @@ interface FieldDefinition<T = any, D extends string = string> {
|
|
|
20
21
|
min: (val: number) => FieldDefinition<T, D>;
|
|
21
22
|
max: (val: number) => FieldDefinition<T, D>;
|
|
22
23
|
transform: <U>(fn: (val: T) => U) => FieldDefinition<U, D>;
|
|
24
|
+
secret: () => FieldDefinition<T, D>;
|
|
23
25
|
url: () => FieldDefinition<T, D>;
|
|
24
26
|
email: () => FieldDefinition<T, D>;
|
|
25
27
|
regex: (pattern: RegExp, message?: string) => FieldDefinition<T, D>;
|
|
@@ -30,6 +32,7 @@ interface EnvError {
|
|
|
30
32
|
key: string;
|
|
31
33
|
error: string;
|
|
32
34
|
value: any;
|
|
35
|
+
isSecret?: boolean;
|
|
33
36
|
}
|
|
34
37
|
type InferSchema<T> = {
|
|
35
38
|
[K in keyof T]: T[K] extends FieldDefinition<infer U, infer D> ? string extends D ? U : U & {
|
|
@@ -9,6 +9,7 @@ interface FieldDefinition<T = any, D extends string = string> {
|
|
|
9
9
|
max?: number;
|
|
10
10
|
options?: T[];
|
|
11
11
|
description?: string;
|
|
12
|
+
isSecret?: boolean;
|
|
12
13
|
validate?: {
|
|
13
14
|
fn: (val: T) => boolean;
|
|
14
15
|
message: string;
|
|
@@ -20,6 +21,7 @@ interface FieldDefinition<T = any, D extends string = string> {
|
|
|
20
21
|
min: (val: number) => FieldDefinition<T, D>;
|
|
21
22
|
max: (val: number) => FieldDefinition<T, D>;
|
|
22
23
|
transform: <U>(fn: (val: T) => U) => FieldDefinition<U, D>;
|
|
24
|
+
secret: () => FieldDefinition<T, D>;
|
|
23
25
|
url: () => FieldDefinition<T, D>;
|
|
24
26
|
email: () => FieldDefinition<T, D>;
|
|
25
27
|
regex: (pattern: RegExp, message?: string) => FieldDefinition<T, D>;
|
|
@@ -30,6 +32,7 @@ interface EnvError {
|
|
|
30
32
|
key: string;
|
|
31
33
|
error: string;
|
|
32
34
|
value: any;
|
|
35
|
+
isSecret?: boolean;
|
|
33
36
|
}
|
|
34
37
|
type InferSchema<T> = {
|
|
35
38
|
[K in keyof T]: T[K] extends FieldDefinition<infer U, infer D> ? string extends D ? U : U & {
|
package/dist/vite.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var
|
|
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;
|
package/dist/vite.d.cts
CHANGED
package/dist/vite.d.ts
CHANGED
package/dist/vite.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as n}from"./chunk-
|
|
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};
|
package/package.json
CHANGED
package/dist/chunk-GCSZ35F2.cjs
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkFH2DFX4Jcjs = require('./chunk-FH2DFX4J.cjs');function $(a){let e={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m"};console.error(`
|
|
2
|
-
${e.r}${e.b}\u274C SafeEnv Error${e.res}
|
|
3
|
-
${e.d}${"".padEnd(40,"-")}${e.res}`),a.forEach(i=>{let d=i.value===void 0?"undefined":`"${i.value}"`;console.error(`${e.y}${i.key}${e.res} ${e.r}${i.error}${e.res} ${e.d}${d}${e.res}`)}),console.error(`${e.d}${"".padEnd(40,"-")}${e.res}
|
|
4
|
-
${e.g}\u{1F4A1} Check your .env files.${e.res}
|
|
5
|
-
`)}function h(a,e={}){let{loadProcessEnv:i=!0,source:d,prefix:p=""}=e,f;if(d!==void 0)f=d||{};else{let n=e.mode||(typeof process<"u"?process.env.NODE_ENV:"development"),o=[".env",`.env.${n}`,".env.local",`.env.${n}.local`],s={};for(let t of o)s={...s,..._chunkFH2DFX4Jcjs.b.call(void 0, t)};f={...s,...i&&typeof process<"u"?process.env:{}}}let E={},c=[];for(let n in a){let o=a[n],s=o.sourceKey;if(!s){let r=p+n;f[r]!==void 0?s=r:f[n]!==void 0?s=n:s=p?r:n}let t=f[s];try{let r;if(t===void 0||t===""&&o.default!==void 0){if(o.required&&t===void 0)throw new Error("Required field missing");r=o.default}else r=o.parse(t);if(r!==void 0&&o.metadata){let{min:l,max:u,validate:m}=o.metadata;if(typeof r=="number"){if(l!==void 0&&r<l)throw new Error(`Below min ${l}`);if(u!==void 0&&r>u)throw new Error(`Above max ${u}`)}if(m&&!m.fn(r))throw new Error(m.message)}E[n]=r}catch(r){c.push({key:s,error:r.message,value:t})}}if(c.length>0){$(c);let n=typeof process<"u"&&!!process.exit,o=typeof process<"u"&&process.env.NODE_ENV==="test";if(n&&!d&&!o)process.exit(1);else throw new Error("SafeEnv: Configuration validation failed.")}return E}exports.a = $; exports.b = h;
|
package/dist/chunk-NRXIL5NF.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import{b as v}from"./chunk-POVTEBYN.js";function $(a){let e={r:"\x1B[31m",g:"\x1B[32m",y:"\x1B[33m",b:"\x1B[1m",res:"\x1B[0m",d:"\x1B[2m"};console.error(`
|
|
2
|
-
${e.r}${e.b}\u274C SafeEnv Error${e.res}
|
|
3
|
-
${e.d}${"".padEnd(40,"-")}${e.res}`),a.forEach(i=>{let d=i.value===void 0?"undefined":`"${i.value}"`;console.error(`${e.y}${i.key}${e.res} ${e.r}${i.error}${e.res} ${e.d}${d}${e.res}`)}),console.error(`${e.d}${"".padEnd(40,"-")}${e.res}
|
|
4
|
-
${e.g}\u{1F4A1} Check your .env files.${e.res}
|
|
5
|
-
`)}function h(a,e={}){let{loadProcessEnv:i=!0,source:d,prefix:p=""}=e,f;if(d!==void 0)f=d||{};else{let n=e.mode||(typeof process<"u"?process.env.NODE_ENV:"development"),o=[".env",`.env.${n}`,".env.local",`.env.${n}.local`],s={};for(let t of o)s={...s,...v(t)};f={...s,...i&&typeof process<"u"?process.env:{}}}let E={},c=[];for(let n in a){let o=a[n],s=o.sourceKey;if(!s){let r=p+n;f[r]!==void 0?s=r:f[n]!==void 0?s=n:s=p?r:n}let t=f[s];try{let r;if(t===void 0||t===""&&o.default!==void 0){if(o.required&&t===void 0)throw new Error("Required field missing");r=o.default}else r=o.parse(t);if(r!==void 0&&o.metadata){let{min:l,max:u,validate:m}=o.metadata;if(typeof r=="number"){if(l!==void 0&&r<l)throw new Error(`Below min ${l}`);if(u!==void 0&&r>u)throw new Error(`Above max ${u}`)}if(m&&!m.fn(r))throw new Error(m.message)}E[n]=r}catch(r){c.push({key:s,error:r.message,value:t})}}if(c.length>0){$(c);let n=typeof process<"u"&&!!process.exit,o=typeof process<"u"&&process.env.NODE_ENV==="test";if(n&&!d&&!o)process.exit(1);else throw new Error("SafeEnv: Configuration validation failed.")}return E}export{$ as a,h as b};
|
package/dist/chunk-POVTEBYN.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import o from"fs";import a from"path";function s(i){let r={},c=i.split(/\r?\n/);for(let f of c){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)),r[l]=t}return r}function h(i=".env"){try{let r=a.resolve(process.cwd(),i);if(o.existsSync(r))return s(o.readFileSync(r,"utf-8"))}catch{}return{}}export{s as a,h as b};
|