dotenv-gad 1.4.1 → 1.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.md +4 -0
- package/dist/client.cjs +32 -0
- package/dist/index.cjs +436 -0
- package/dist/vite-plugin.js +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# dotenv-gad
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/dotenv-gad)
|
|
4
|
+
[](https://github.com/kasimlyee/dotenv-gad/actions/workflows/ci.yml)
|
|
4
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
5
8
|
[](https://kasimlyee.github.io/dotenv-gad/)
|
|
9
|
+
[](https://www.npmjs.com/package/dotenv-gad)
|
|
6
10
|
|
|
7
11
|
**dotenv-gad** is an environment variable validation library that brings type safety, schema validation, and runtime checks to your Node.js and JavaScript applications. It works with any environment variable source — `.env` files, platform dashboards (Vercel, Railway, Docker), CI/CD pipelines, or `process.env` directly.
|
|
8
12
|
|
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/client.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
default: () => client_default,
|
|
24
|
+
env: () => env
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(client_exports);
|
|
27
|
+
var env = {};
|
|
28
|
+
var client_default = env;
|
|
29
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
30
|
+
0 && (module.exports = {
|
|
31
|
+
env
|
|
32
|
+
});
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
AggregateError: () => AggregateError,
|
|
34
|
+
EnvAggregateError: () => EnvAggregateError,
|
|
35
|
+
EnvValidationError: () => EnvValidationError,
|
|
36
|
+
EnvValidator: () => EnvValidator,
|
|
37
|
+
composeSchema: () => composeSchema,
|
|
38
|
+
createEnvProxy: () => createEnvProxy,
|
|
39
|
+
defineSchema: () => defineSchema,
|
|
40
|
+
loadEnv: () => loadEnv,
|
|
41
|
+
validateEnv: () => validateEnv
|
|
42
|
+
});
|
|
43
|
+
module.exports = __toCommonJS(src_exports);
|
|
44
|
+
|
|
45
|
+
// src/errors.ts
|
|
46
|
+
var EnvValidationError = class extends Error {
|
|
47
|
+
constructor(key, message, receiveValue) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.key = key;
|
|
50
|
+
this.message = message;
|
|
51
|
+
this.receiveValue = receiveValue;
|
|
52
|
+
this.name = "EnvValidationError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var EnvAggregateError = class _EnvAggregateError extends Error {
|
|
56
|
+
constructor(errors, message) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.errors = errors;
|
|
59
|
+
this.name = "EnvAggregateError";
|
|
60
|
+
Object.setPrototypeOf(this, _EnvAggregateError.prototype);
|
|
61
|
+
}
|
|
62
|
+
toString() {
|
|
63
|
+
const errorList = this.errors.map((e) => {
|
|
64
|
+
let msg = ` - ${e.key}: ${e.message}`;
|
|
65
|
+
if (e.value !== void 0)
|
|
66
|
+
msg += ` (received: ${JSON.stringify(e.value)})`;
|
|
67
|
+
if (e.rule?.docs) msg += `
|
|
68
|
+
${e.rule.docs}`;
|
|
69
|
+
return msg;
|
|
70
|
+
}).join("\n");
|
|
71
|
+
return `${this.message}:
|
|
72
|
+
${errorList}`;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var AggregateError = EnvAggregateError;
|
|
76
|
+
|
|
77
|
+
// src/validator.ts
|
|
78
|
+
var EnvValidator = class {
|
|
79
|
+
/**
|
|
80
|
+
* Constructs a new EnvValidator instance.
|
|
81
|
+
* @param {SchemaDefinition} schema The schema definition for the environment variables.
|
|
82
|
+
* @param {Object} [options] Optional options for the validation process.
|
|
83
|
+
* @param {boolean} [options.strict] When true, environment variables not present in the schema will be rejected.
|
|
84
|
+
*/
|
|
85
|
+
constructor(schema, options) {
|
|
86
|
+
this.schema = schema;
|
|
87
|
+
this.options = options;
|
|
88
|
+
}
|
|
89
|
+
errors = [];
|
|
90
|
+
validate(env) {
|
|
91
|
+
this.errors = [];
|
|
92
|
+
const result = {};
|
|
93
|
+
const groupedEnv = {};
|
|
94
|
+
const prefixes = [];
|
|
95
|
+
for (const [k, r] of Object.entries(this.schema)) {
|
|
96
|
+
const eff = this.getEffectiveRule(k, r);
|
|
97
|
+
if (eff.type === "object" && eff.properties) {
|
|
98
|
+
const prefix = eff.envPrefix ?? `${k}_`;
|
|
99
|
+
prefixes.push({ key: k, prefix });
|
|
100
|
+
groupedEnv[k] = {};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const envKeys = Object.keys(env);
|
|
104
|
+
for (let i = 0; i < envKeys.length; i++) {
|
|
105
|
+
const eKey = envKeys[i];
|
|
106
|
+
for (let j = 0; j < prefixes.length; j++) {
|
|
107
|
+
const { key, prefix } = prefixes[j];
|
|
108
|
+
if (eKey.startsWith(prefix)) {
|
|
109
|
+
const subKey = eKey.slice(prefix.length);
|
|
110
|
+
groupedEnv[key][subKey] = env[eKey];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const schemaKeys = Object.keys(this.schema);
|
|
115
|
+
for (let i = 0; i < schemaKeys.length; i++) {
|
|
116
|
+
const key = schemaKeys[i];
|
|
117
|
+
const rule = this.schema[key];
|
|
118
|
+
try {
|
|
119
|
+
const valToValidate = groupedEnv[key] && Object.keys(groupedEnv[key]).length > 0 ? groupedEnv[key] : env[key];
|
|
120
|
+
if (groupedEnv[key] && Object.keys(groupedEnv[key]).length > 0 && env[key] !== void 0) {
|
|
121
|
+
console.warn(`Both prefixed variables and top-level ${key} exist; prefixed vars are used`);
|
|
122
|
+
}
|
|
123
|
+
if (this.options?.strict && groupedEnv[key] && Object.keys(groupedEnv[key]).length > 0) {
|
|
124
|
+
const propNames = rule.properties ? Object.keys(rule.properties) : [];
|
|
125
|
+
const extras = Object.keys(groupedEnv[key]).filter((s) => !propNames.includes(s));
|
|
126
|
+
if (extras.length > 0) {
|
|
127
|
+
this.errors.push({
|
|
128
|
+
key,
|
|
129
|
+
message: `Unexpected grouped environment variables: ${extras.join(", ")}`,
|
|
130
|
+
value: Object.keys(groupedEnv[key]),
|
|
131
|
+
rule
|
|
132
|
+
});
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
result[key] = this.validateKey(key, rule, valToValidate);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error instanceof Error) {
|
|
139
|
+
let displayedValue;
|
|
140
|
+
if (env[key] === void 0) {
|
|
141
|
+
displayedValue = void 0;
|
|
142
|
+
} else if (this.options?.includeRaw) {
|
|
143
|
+
if (rule.sensitive && !this.options?.includeSensitive) {
|
|
144
|
+
displayedValue = "****";
|
|
145
|
+
} else {
|
|
146
|
+
displayedValue = env[key];
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
displayedValue = this.redactValue(env[key], rule.sensitive);
|
|
150
|
+
}
|
|
151
|
+
this.errors.push({
|
|
152
|
+
key,
|
|
153
|
+
message: error.message,
|
|
154
|
+
value: displayedValue,
|
|
155
|
+
rule
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (this.options?.strict) {
|
|
161
|
+
const prefixedKeys = /* @__PURE__ */ new Set();
|
|
162
|
+
for (const p of prefixes) {
|
|
163
|
+
for (const eKey of envKeys) {
|
|
164
|
+
if (eKey.startsWith(p.prefix)) prefixedKeys.add(eKey);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const k of envKeys) {
|
|
168
|
+
if (!(k in this.schema) && !prefixedKeys.has(k)) {
|
|
169
|
+
this.errors.push({
|
|
170
|
+
key: k,
|
|
171
|
+
message: `Unexpected environment variable`
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (this.errors.length > 0) {
|
|
177
|
+
const keys = this.errors.map((e) => e.key).join(", ");
|
|
178
|
+
throw new EnvAggregateError(
|
|
179
|
+
this.errors,
|
|
180
|
+
`Environment validation failed: ${keys}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
// Redact or trim sensitive values for error reporting
|
|
186
|
+
redactValue(value, sensitive) {
|
|
187
|
+
if (value === void 0) return void 0;
|
|
188
|
+
if (sensitive) return "****";
|
|
189
|
+
if (typeof value !== "string") return value;
|
|
190
|
+
if (value.length > 64) {
|
|
191
|
+
return `${value.slice(0, 4)}...${value.slice(-4)}`;
|
|
192
|
+
}
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
// Try to quickly determine if a string *might* be JSON before parsing to avoid
|
|
196
|
+
// costly exceptions in the hot path for clearly non-JSON values.
|
|
197
|
+
tryParseJSON(value) {
|
|
198
|
+
if (typeof value !== "string") return { ok: false };
|
|
199
|
+
const s = value.trim();
|
|
200
|
+
if (!s) return { ok: false };
|
|
201
|
+
const c = s[0];
|
|
202
|
+
if (c !== "{" && c !== "[" && c !== '"' && c !== "t" && c !== "f" && c !== "n" && (c < "0" || c > "9") && c !== "-") {
|
|
203
|
+
return { ok: false };
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
return { ok: true, value: JSON.parse(s) };
|
|
207
|
+
} catch {
|
|
208
|
+
return { ok: false };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
validateKey(key, rule, value) {
|
|
212
|
+
const effectiveRule = this.getEffectiveRule(key, rule);
|
|
213
|
+
if (value === void 0 || value === "") {
|
|
214
|
+
if (effectiveRule.required)
|
|
215
|
+
throw new Error(`Missing required environment variable`);
|
|
216
|
+
return effectiveRule.default;
|
|
217
|
+
}
|
|
218
|
+
if (effectiveRule.transform) {
|
|
219
|
+
value = effectiveRule.transform(value);
|
|
220
|
+
}
|
|
221
|
+
switch (effectiveRule.type) {
|
|
222
|
+
case "string":
|
|
223
|
+
value = String(value).trim();
|
|
224
|
+
if (effectiveRule.minLength !== void 0 && value.length < effectiveRule.minLength) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
`Environment variable ${key} must be at least ${effectiveRule.minLength} characters`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if (effectiveRule.maxLength !== void 0 && value.length > effectiveRule.maxLength) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`Environment variable ${key} must be at most ${effectiveRule.maxLength} characters`
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
case "number":
|
|
236
|
+
value = Number(value);
|
|
237
|
+
if (isNaN(value)) {
|
|
238
|
+
throw new Error(`Environment variable ${key} must be a number`);
|
|
239
|
+
}
|
|
240
|
+
if (effectiveRule.min !== void 0 && value < effectiveRule.min) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
`Environment variable ${key} must be at least ${effectiveRule.min}`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
if (effectiveRule.max !== void 0 && value > effectiveRule.max) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`Environment variable ${key} must be at most ${effectiveRule.max}`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
case "boolean":
|
|
252
|
+
if (typeof value === "string") {
|
|
253
|
+
value = value.toLowerCase();
|
|
254
|
+
if (value === "true") {
|
|
255
|
+
value = true;
|
|
256
|
+
} else if (value === "false") {
|
|
257
|
+
value = false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (typeof value !== "boolean") {
|
|
261
|
+
throw new Error(
|
|
262
|
+
`Environment variable ${key} must be a boolean (true/false)`
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
value = Boolean(value);
|
|
266
|
+
break;
|
|
267
|
+
case "date":
|
|
268
|
+
const date = new Date(value);
|
|
269
|
+
if (isNaN(date.getTime())) {
|
|
270
|
+
throw new Error(`Environment variable ${key} must be a valid date`);
|
|
271
|
+
}
|
|
272
|
+
value = date;
|
|
273
|
+
break;
|
|
274
|
+
case "url":
|
|
275
|
+
try {
|
|
276
|
+
new URL(String(value));
|
|
277
|
+
} catch {
|
|
278
|
+
throw new Error("Must be a valid URL");
|
|
279
|
+
}
|
|
280
|
+
break;
|
|
281
|
+
case "email":
|
|
282
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value))) {
|
|
283
|
+
throw new Error("Must be a valid email");
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
case "ip":
|
|
287
|
+
if (!/^(?:(?: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(value))) {
|
|
288
|
+
throw new Error("Must be a valid IP address");
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
case "port":
|
|
292
|
+
const port = Number(value);
|
|
293
|
+
if (isNaN(port) || !Number.isInteger(port)) throw new Error("Must be an integer");
|
|
294
|
+
if (port < 1 || port > 65535) {
|
|
295
|
+
throw new Error("Must be between 1 and 65535");
|
|
296
|
+
}
|
|
297
|
+
value = port;
|
|
298
|
+
break;
|
|
299
|
+
case "json":
|
|
300
|
+
const maybeJson = this.tryParseJSON(value);
|
|
301
|
+
if (!maybeJson.ok) {
|
|
302
|
+
throw new Error("Must be valid JSON");
|
|
303
|
+
}
|
|
304
|
+
value = maybeJson.value;
|
|
305
|
+
break;
|
|
306
|
+
case "array":
|
|
307
|
+
if (!Array.isArray(value)) {
|
|
308
|
+
const parsed = this.tryParseJSON(value);
|
|
309
|
+
if (!parsed.ok || !Array.isArray(parsed.value)) {
|
|
310
|
+
throw new Error("Must be a valid array or JSON array string");
|
|
311
|
+
}
|
|
312
|
+
value = parsed.value;
|
|
313
|
+
}
|
|
314
|
+
if (effectiveRule.items) {
|
|
315
|
+
value = value.map((item, i) => {
|
|
316
|
+
try {
|
|
317
|
+
return this.validateKey(
|
|
318
|
+
`${key}[${i}]`,
|
|
319
|
+
effectiveRule.items,
|
|
320
|
+
item
|
|
321
|
+
);
|
|
322
|
+
} catch (error) {
|
|
323
|
+
throw new Error(`Array item '${i}':${error.message}`);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
case "object":
|
|
329
|
+
if (typeof value === "string") {
|
|
330
|
+
const parsed = this.tryParseJSON(value);
|
|
331
|
+
if (!parsed.ok || typeof parsed.value !== "object" || Array.isArray(parsed.value)) {
|
|
332
|
+
throw new Error("Must be a valid object or JSON string");
|
|
333
|
+
}
|
|
334
|
+
value = parsed.value;
|
|
335
|
+
}
|
|
336
|
+
if (effectiveRule.properties) {
|
|
337
|
+
const obj = {};
|
|
338
|
+
for (const prop in effectiveRule.properties) {
|
|
339
|
+
if (!Object.prototype.hasOwnProperty.call(effectiveRule.properties, prop)) continue;
|
|
340
|
+
const propRule = effectiveRule.properties[prop];
|
|
341
|
+
try {
|
|
342
|
+
obj[prop] = this.validateKey(
|
|
343
|
+
`${key}.${prop}`,
|
|
344
|
+
propRule,
|
|
345
|
+
value[prop]
|
|
346
|
+
);
|
|
347
|
+
} catch (error) {
|
|
348
|
+
throw new Error(`Property '${prop}':${error.message}`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
value = obj;
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
if (effectiveRule.enum && !effectiveRule.enum.includes(value)) {
|
|
356
|
+
throw new Error(
|
|
357
|
+
`Environment variable ${key} must be one of ${effectiveRule.enum.join(
|
|
358
|
+
", "
|
|
359
|
+
)}`
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
if (effectiveRule.regex && !effectiveRule.regex.test(String(value))) {
|
|
363
|
+
throw new Error(
|
|
364
|
+
effectiveRule.regexError || `Environment variable ${key} must match ${effectiveRule.regex}`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
if (effectiveRule.validate && !effectiveRule.validate(value)) {
|
|
368
|
+
throw new Error(effectiveRule.error || "Custom validation failed");
|
|
369
|
+
}
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
372
|
+
getEffectiveRule(key, rule) {
|
|
373
|
+
const envName = process.env.NODE_ENV || "development";
|
|
374
|
+
const envRule = rule.env?.[envName] || {};
|
|
375
|
+
return { ...rule, ...envRule };
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// src/schema.ts
|
|
380
|
+
function defineSchema(schema) {
|
|
381
|
+
return schema;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/utils.ts
|
|
385
|
+
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
386
|
+
function loadEnv(schema, options) {
|
|
387
|
+
const fileEnv = import_dotenv.default.config({ debug: false, path: options?.path }).parsed || {};
|
|
388
|
+
const env = { ...process.env, ...fileEnv };
|
|
389
|
+
const validator = new EnvValidator(schema, options);
|
|
390
|
+
return validator.validate(env);
|
|
391
|
+
}
|
|
392
|
+
function createEnvProxy(validatedEnv) {
|
|
393
|
+
return new Proxy(validatedEnv, {
|
|
394
|
+
get(target, prop) {
|
|
395
|
+
if (typeof prop === "string" && !(prop in target)) {
|
|
396
|
+
throw new Error(
|
|
397
|
+
`Environment variable ${prop} is not validated`
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
return target[prop];
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/compose.ts
|
|
406
|
+
function composeSchema(...schemas) {
|
|
407
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
408
|
+
for (const schema of schemas) {
|
|
409
|
+
for (const key of Object.keys(schema)) {
|
|
410
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
411
|
+
result[key] = schema[key];
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return result;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/index.ts
|
|
418
|
+
var import_dotenv2 = __toESM(require("dotenv"), 1);
|
|
419
|
+
function validateEnv(schema, options) {
|
|
420
|
+
const fileEnv = import_dotenv2.default.config({ debug: false, path: options?.path }).parsed || {};
|
|
421
|
+
const env = { ...process.env, ...fileEnv };
|
|
422
|
+
const validator = new EnvValidator(schema, options);
|
|
423
|
+
return validator.validate(env);
|
|
424
|
+
}
|
|
425
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
426
|
+
0 && (module.exports = {
|
|
427
|
+
AggregateError,
|
|
428
|
+
EnvAggregateError,
|
|
429
|
+
EnvValidationError,
|
|
430
|
+
EnvValidator,
|
|
431
|
+
composeSchema,
|
|
432
|
+
createEnvProxy,
|
|
433
|
+
defineSchema,
|
|
434
|
+
loadEnv,
|
|
435
|
+
validateEnv
|
|
436
|
+
});
|
package/dist/vite-plugin.js
CHANGED
|
@@ -71,7 +71,7 @@ function generateDtsContent(filteredKeys, schemaAbsPath, dtsAbsPath) {
|
|
|
71
71
|
"// ──────────────────────────────────────────────────────────────",
|
|
72
72
|
"",
|
|
73
73
|
'declare module "dotenv-gad/client" {',
|
|
74
|
-
` interface DotenvGadEnv extends ${envType} {}`,
|
|
74
|
+
` export interface DotenvGadEnv extends ${envType} {}`,
|
|
75
75
|
" export const env: DotenvGadEnv;",
|
|
76
76
|
" export default env;",
|
|
77
77
|
"}",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotenv-gad",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/types/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"dotenv-gad": "./dist/cli/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc -p tsconfig.build.json",
|
|
11
|
+
"build": "tsc -p tsconfig.build.json && tsup",
|
|
12
12
|
"test": "vitest run",
|
|
13
13
|
"test:watch": "vitest",
|
|
14
14
|
"test:coverage": "vitest run --coverage",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"exports": {
|
|
41
41
|
".": {
|
|
42
42
|
"types": "./dist/types/index.d.ts",
|
|
43
|
-
"import": "./dist/index.js"
|
|
43
|
+
"import": "./dist/index.js",
|
|
44
|
+
"require": "./dist/index.cjs"
|
|
44
45
|
},
|
|
45
46
|
"./vite": {
|
|
46
47
|
"types": "./dist/types/vite-plugin.d.ts",
|
|
@@ -48,12 +49,14 @@
|
|
|
48
49
|
},
|
|
49
50
|
"./client": {
|
|
50
51
|
"types": "./dist/types/client.d.ts",
|
|
51
|
-
"import": "./dist/client.js"
|
|
52
|
+
"import": "./dist/client.js",
|
|
53
|
+
"require": "./dist/client.cjs"
|
|
52
54
|
},
|
|
53
55
|
"./package.json": "./package.json"
|
|
54
56
|
},
|
|
55
57
|
"files": [
|
|
56
58
|
"dist/**/*.js",
|
|
59
|
+
"dist/**/*.cjs",
|
|
57
60
|
"dist/**/*.d.ts",
|
|
58
61
|
"README.md",
|
|
59
62
|
"LICENSE"
|
|
@@ -78,6 +81,7 @@
|
|
|
78
81
|
"globals": "^15.14.0",
|
|
79
82
|
"husky": "^9.1.7",
|
|
80
83
|
"prettier": "^3.4.2",
|
|
84
|
+
"tsup": "^8.5.1",
|
|
81
85
|
"typescript": "^5.7.0",
|
|
82
86
|
"typescript-eslint": "^8.19.1",
|
|
83
87
|
"vite": "^6.0.0",
|