dev-env-toolkit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,491 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { resolve } from 'path';
3
+
4
+ // src/utils/errors.ts
5
+ var EnvValidationException = class _EnvValidationException extends Error {
6
+ errors;
7
+ constructor(errors) {
8
+ const message = formatValidationErrors(errors);
9
+ super(message);
10
+ this.name = "EnvValidationException";
11
+ this.errors = errors;
12
+ if (Error.captureStackTrace) {
13
+ Error.captureStackTrace(this, _EnvValidationException);
14
+ }
15
+ }
16
+ };
17
+ function formatValidationErrors(errors) {
18
+ const lines = [
19
+ "",
20
+ "\x1B[31m\x1B[1mEnvironment Validation Failed\x1B[0m",
21
+ "",
22
+ `Found ${errors.length} error${errors.length > 1 ? "s" : ""}:`,
23
+ ""
24
+ ];
25
+ for (const error of errors) {
26
+ lines.push(` \x1B[33m${error.key}\x1B[0m: ${error.message}`);
27
+ if (error.value !== void 0) {
28
+ lines.push(` Received: \x1B[90m${error.value || "(empty)"}\x1B[0m`);
29
+ }
30
+ if (error.expected) {
31
+ lines.push(` Expected: \x1B[90m${error.expected}\x1B[0m`);
32
+ }
33
+ lines.push("");
34
+ }
35
+ lines.push("\x1B[36mTip:\x1B[0m Check your .env file or environment variables");
36
+ lines.push("");
37
+ return lines.join("\n");
38
+ }
39
+ var EnvParseError = class _EnvParseError extends Error {
40
+ key;
41
+ value;
42
+ constructor(key, message, value) {
43
+ super(`${key}: ${message}`);
44
+ this.name = "EnvParseError";
45
+ this.key = key;
46
+ this.value = value;
47
+ if (Error.captureStackTrace) {
48
+ Error.captureStackTrace(this, _EnvParseError);
49
+ }
50
+ }
51
+ };
52
+
53
+ // src/env/validators.ts
54
+ var TRUE_VALUES = /* @__PURE__ */ new Set(["true", "1", "yes", "on"]);
55
+ var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "0", "no", "off"]);
56
+ var OPTIONAL_MISSING = /* @__PURE__ */ Symbol("optional");
57
+ var BaseValidator = class {
58
+ _type;
59
+ _optional = false;
60
+ _default;
61
+ optional() {
62
+ const clone = this.clone();
63
+ clone._optional = true;
64
+ return clone;
65
+ }
66
+ default(value) {
67
+ const clone = this.clone();
68
+ clone._default = value;
69
+ return clone;
70
+ }
71
+ getRequired(value, key) {
72
+ if (value === void 0 || value === "") {
73
+ if (this._default !== void 0) {
74
+ throw new DefaultValueUsed(this._default);
75
+ }
76
+ if (this._optional) {
77
+ return OPTIONAL_MISSING;
78
+ }
79
+ throw new EnvParseError(key, "Required environment variable is missing");
80
+ }
81
+ return value;
82
+ }
83
+ };
84
+ var DefaultValueUsed = class {
85
+ constructor(value) {
86
+ this.value = value;
87
+ }
88
+ };
89
+ var StringValidatorImpl = class _StringValidatorImpl extends BaseValidator {
90
+ constraints = [];
91
+ parse(value, key) {
92
+ try {
93
+ const str = this.getRequired(value, key);
94
+ if (str === OPTIONAL_MISSING) return void 0;
95
+ for (const constraint of this.constraints) {
96
+ constraint(str, key);
97
+ }
98
+ return str;
99
+ } catch (e) {
100
+ if (e instanceof DefaultValueUsed) return e.value;
101
+ throw e;
102
+ }
103
+ }
104
+ min(length) {
105
+ const clone = this.clone();
106
+ clone.constraints.push((value, key) => {
107
+ if (value.length < length) {
108
+ throw new EnvParseError(
109
+ key,
110
+ `String must be at least ${length} characters`,
111
+ value
112
+ );
113
+ }
114
+ });
115
+ return clone;
116
+ }
117
+ max(length) {
118
+ const clone = this.clone();
119
+ clone.constraints.push((value, key) => {
120
+ if (value.length > length) {
121
+ throw new EnvParseError(
122
+ key,
123
+ `String must be at most ${length} characters`,
124
+ value
125
+ );
126
+ }
127
+ });
128
+ return clone;
129
+ }
130
+ url() {
131
+ const clone = this.clone();
132
+ clone.constraints.push((value, key) => {
133
+ try {
134
+ new URL(value);
135
+ } catch {
136
+ throw new EnvParseError(key, "Invalid URL format", value);
137
+ }
138
+ });
139
+ return clone;
140
+ }
141
+ email() {
142
+ const clone = this.clone();
143
+ clone.constraints.push((value, key) => {
144
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
145
+ if (!emailRegex.test(value)) {
146
+ throw new EnvParseError(key, "Invalid email format", value);
147
+ }
148
+ });
149
+ return clone;
150
+ }
151
+ regex(pattern) {
152
+ const clone = this.clone();
153
+ clone.constraints.push((value, key) => {
154
+ if (!pattern.test(value)) {
155
+ throw new EnvParseError(
156
+ key,
157
+ `String does not match pattern ${pattern}`,
158
+ value
159
+ );
160
+ }
161
+ });
162
+ return clone;
163
+ }
164
+ clone() {
165
+ const clone = new _StringValidatorImpl();
166
+ clone._optional = this._optional;
167
+ clone._default = this._default;
168
+ clone.constraints = [...this.constraints];
169
+ return clone;
170
+ }
171
+ };
172
+ var NumberValidatorImpl = class _NumberValidatorImpl extends BaseValidator {
173
+ constraints = [];
174
+ parse(value, key) {
175
+ try {
176
+ const str = this.getRequired(value, key);
177
+ if (str === OPTIONAL_MISSING) return void 0;
178
+ const num = Number(str);
179
+ if (isNaN(num)) {
180
+ throw new EnvParseError(key, "Invalid number format", str);
181
+ }
182
+ for (const constraint of this.constraints) {
183
+ constraint(num, key);
184
+ }
185
+ return num;
186
+ } catch (e) {
187
+ if (e instanceof DefaultValueUsed) return e.value;
188
+ throw e;
189
+ }
190
+ }
191
+ min(minValue) {
192
+ const clone = this.clone();
193
+ clone.constraints.push((value, key) => {
194
+ if (value < minValue) {
195
+ throw new EnvParseError(
196
+ key,
197
+ `Number must be at least ${minValue}`,
198
+ String(value)
199
+ );
200
+ }
201
+ });
202
+ return clone;
203
+ }
204
+ max(maxValue) {
205
+ const clone = this.clone();
206
+ clone.constraints.push((value, key) => {
207
+ if (value > maxValue) {
208
+ throw new EnvParseError(
209
+ key,
210
+ `Number must be at most ${maxValue}`,
211
+ String(value)
212
+ );
213
+ }
214
+ });
215
+ return clone;
216
+ }
217
+ int() {
218
+ const clone = this.clone();
219
+ clone.constraints.push((value, key) => {
220
+ if (!Number.isInteger(value)) {
221
+ throw new EnvParseError(key, "Number must be an integer", String(value));
222
+ }
223
+ });
224
+ return clone;
225
+ }
226
+ positive() {
227
+ const clone = this.clone();
228
+ clone.constraints.push((value, key) => {
229
+ if (value <= 0) {
230
+ throw new EnvParseError(key, "Number must be positive", String(value));
231
+ }
232
+ });
233
+ return clone;
234
+ }
235
+ port() {
236
+ return this.int().min(1).max(65535);
237
+ }
238
+ clone() {
239
+ const clone = new _NumberValidatorImpl();
240
+ clone._optional = this._optional;
241
+ clone._default = this._default;
242
+ clone.constraints = [...this.constraints];
243
+ return clone;
244
+ }
245
+ };
246
+ var BooleanValidatorImpl = class _BooleanValidatorImpl extends BaseValidator {
247
+ parse(value, key) {
248
+ try {
249
+ const str = this.getRequired(value, key);
250
+ if (str === OPTIONAL_MISSING) return void 0;
251
+ const lower = str.toLowerCase();
252
+ if (TRUE_VALUES.has(lower)) return true;
253
+ if (FALSE_VALUES.has(lower)) return false;
254
+ throw new EnvParseError(
255
+ key,
256
+ "Invalid boolean value. Expected: true, false, 1, 0, yes, no, on, off",
257
+ lower
258
+ );
259
+ } catch (e) {
260
+ if (e instanceof DefaultValueUsed) return e.value;
261
+ throw e;
262
+ }
263
+ }
264
+ clone() {
265
+ const clone = new _BooleanValidatorImpl();
266
+ clone._optional = this._optional;
267
+ clone._default = this._default;
268
+ return clone;
269
+ }
270
+ };
271
+ var EnumValidatorImpl = class _EnumValidatorImpl extends BaseValidator {
272
+ constructor(values) {
273
+ super();
274
+ this.values = values;
275
+ }
276
+ parse(value, key) {
277
+ try {
278
+ const str = this.getRequired(value, key);
279
+ if (str === OPTIONAL_MISSING) return void 0;
280
+ if (!this.values.includes(str)) {
281
+ throw new EnvParseError(
282
+ key,
283
+ `Invalid enum value. Expected one of: ${this.values.join(", ")}`,
284
+ str
285
+ );
286
+ }
287
+ return str;
288
+ } catch (e) {
289
+ if (e instanceof DefaultValueUsed) return e.value;
290
+ throw e;
291
+ }
292
+ }
293
+ clone() {
294
+ const clone = new _EnumValidatorImpl(this.values);
295
+ clone._optional = this._optional;
296
+ clone._default = this._default;
297
+ return clone;
298
+ }
299
+ };
300
+ var ArrayValidatorImpl = class _ArrayValidatorImpl extends BaseValidator {
301
+ sep = ",";
302
+ constraints = [];
303
+ parse(value, key) {
304
+ try {
305
+ const str = this.getRequired(value, key);
306
+ if (str === OPTIONAL_MISSING) return void 0;
307
+ const arr = str.split(this.sep).map((s) => s.trim()).filter((s) => s.length > 0);
308
+ for (const constraint of this.constraints) {
309
+ constraint(arr, key);
310
+ }
311
+ return arr;
312
+ } catch (e) {
313
+ if (e instanceof DefaultValueUsed) return e.value;
314
+ throw e;
315
+ }
316
+ }
317
+ separator(sep) {
318
+ const clone = this.clone();
319
+ clone.sep = sep;
320
+ return clone;
321
+ }
322
+ min(length) {
323
+ const clone = this.clone();
324
+ clone.constraints.push((value, key) => {
325
+ if (value.length < length) {
326
+ throw new EnvParseError(
327
+ key,
328
+ `Array must have at least ${length} items`,
329
+ value.join(this.sep)
330
+ );
331
+ }
332
+ });
333
+ return clone;
334
+ }
335
+ max(length) {
336
+ const clone = this.clone();
337
+ clone.constraints.push((value, key) => {
338
+ if (value.length > length) {
339
+ throw new EnvParseError(
340
+ key,
341
+ `Array must have at most ${length} items`,
342
+ value.join(this.sep)
343
+ );
344
+ }
345
+ });
346
+ return clone;
347
+ }
348
+ clone() {
349
+ const clone = new _ArrayValidatorImpl();
350
+ clone._optional = this._optional;
351
+ clone._default = this._default;
352
+ clone.sep = this.sep;
353
+ clone.constraints = [...this.constraints];
354
+ return clone;
355
+ }
356
+ };
357
+ var validators = {
358
+ string: () => new StringValidatorImpl(),
359
+ number: () => new NumberValidatorImpl(),
360
+ boolean: () => new BooleanValidatorImpl(),
361
+ enum: (values) => new EnumValidatorImpl(values),
362
+ array: () => new ArrayValidatorImpl()
363
+ };
364
+ function parseEnvFile(filePath) {
365
+ const absolutePath = resolve(process.cwd(), filePath);
366
+ if (!existsSync(absolutePath)) {
367
+ return {};
368
+ }
369
+ const content = readFileSync(absolutePath, "utf-8");
370
+ return parseEnvContent(content);
371
+ }
372
+ function parseEnvContent(content) {
373
+ const result = {};
374
+ const lines = content.split(/\r?\n/);
375
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
376
+ const line = lines[lineNum].trim();
377
+ if (!line || line.startsWith("#")) {
378
+ continue;
379
+ }
380
+ const equalsIndex = line.indexOf("=");
381
+ if (equalsIndex === -1) {
382
+ continue;
383
+ }
384
+ const key = line.substring(0, equalsIndex).trim();
385
+ let value = line.substring(equalsIndex + 1).trim();
386
+ if (!key) {
387
+ continue;
388
+ }
389
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
390
+ value = value.slice(1, -1);
391
+ if (line.substring(equalsIndex + 1).trim().startsWith('"')) {
392
+ value = value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
393
+ }
394
+ } else {
395
+ const commentIndex = value.indexOf("#");
396
+ if (commentIndex !== -1) {
397
+ value = value.substring(0, commentIndex).trim();
398
+ }
399
+ }
400
+ result[key] = value;
401
+ }
402
+ return result;
403
+ }
404
+ function loadEnvFile(filePath = ".env", options = {}) {
405
+ const parsed = parseEnvFile(filePath);
406
+ for (const [key, value] of Object.entries(parsed)) {
407
+ if (options.override || process.env[key] === void 0) {
408
+ process.env[key] = value;
409
+ }
410
+ }
411
+ return parsed;
412
+ }
413
+
414
+ // src/env/index.ts
415
+ function create(schema, options = {}) {
416
+ const { path, throwOnError = true, env: customEnv } = options;
417
+ if (path) {
418
+ loadEnvFile(path);
419
+ }
420
+ const envSource = customEnv ?? process.env;
421
+ const errors = [];
422
+ const result = {};
423
+ for (const [key, validator] of Object.entries(schema)) {
424
+ try {
425
+ const value = envSource[key];
426
+ result[key] = validator.parse(value, key);
427
+ } catch (error) {
428
+ if (error instanceof EnvParseError) {
429
+ errors.push({
430
+ key: error.key,
431
+ message: error.message.replace(`${error.key}: `, ""),
432
+ value: error.value
433
+ });
434
+ } else {
435
+ throw error;
436
+ }
437
+ }
438
+ }
439
+ if (errors.length > 0 && throwOnError) {
440
+ throw new EnvValidationException(errors);
441
+ }
442
+ return result;
443
+ }
444
+ function safeParse(schema, options = {}) {
445
+ const { path, env: customEnv } = options;
446
+ if (path) {
447
+ loadEnvFile(path);
448
+ }
449
+ const envSource = customEnv ?? process.env;
450
+ const errors = [];
451
+ const result = {};
452
+ for (const [key, validator] of Object.entries(schema)) {
453
+ try {
454
+ const value = envSource[key];
455
+ result[key] = validator.parse(value, key);
456
+ } catch (error) {
457
+ if (error instanceof EnvParseError) {
458
+ errors.push({
459
+ key: error.key,
460
+ message: error.message.replace(`${error.key}: `, ""),
461
+ value: error.value
462
+ });
463
+ } else {
464
+ throw error;
465
+ }
466
+ }
467
+ }
468
+ if (errors.length > 0) {
469
+ return { success: false, errors };
470
+ }
471
+ return { success: true, data: result };
472
+ }
473
+ var env = {
474
+ // Schema creation
475
+ create,
476
+ safeParse,
477
+ // Validators
478
+ string: validators.string,
479
+ number: validators.number,
480
+ boolean: validators.boolean,
481
+ enum: validators.enum,
482
+ array: validators.array,
483
+ // File utilities
484
+ load: loadEnvFile,
485
+ parse: parseEnvFile
486
+ };
487
+ var env_default = env;
488
+
489
+ export { EnvParseError, EnvValidationException, env_default as default, env };
490
+ //# sourceMappingURL=index.js.map
491
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/errors.ts","../src/env/validators.ts","../src/env/parser.ts","../src/env/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { EnvValidationError } from '../env/types.js';\n\n/**\n * Custom error class for environment validation errors\n */\nexport class EnvValidationException extends Error {\n public readonly errors: EnvValidationError[];\n\n constructor(errors: EnvValidationError[]) {\n const message = formatValidationErrors(errors);\n super(message);\n this.name = 'EnvValidationException';\n this.errors = errors;\n\n // Maintains proper stack trace for where our error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EnvValidationException);\n }\n }\n}\n\n/**\n * Format validation errors into a readable message\n */\nfunction formatValidationErrors(errors: EnvValidationError[]): string {\n const lines = [\n '',\n '\\x1b[31m\\x1b[1mEnvironment Validation Failed\\x1b[0m',\n '',\n `Found ${errors.length} error${errors.length > 1 ? 's' : ''}:`,\n '',\n ];\n\n for (const error of errors) {\n lines.push(` \\x1b[33m${error.key}\\x1b[0m: ${error.message}`);\n if (error.value !== undefined) {\n lines.push(` Received: \\x1b[90m${error.value || '(empty)'}\\x1b[0m`);\n }\n if (error.expected) {\n lines.push(` Expected: \\x1b[90m${error.expected}\\x1b[0m`);\n }\n lines.push('');\n }\n\n lines.push('\\x1b[36mTip:\\x1b[0m Check your .env file or environment variables');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Custom error for parsing errors\n */\nexport class EnvParseError extends Error {\n public readonly key: string;\n public readonly value?: string;\n\n constructor(key: string, message: string, value?: string) {\n super(`${key}: ${message}`);\n this.name = 'EnvParseError';\n this.key = key;\n this.value = value;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EnvParseError);\n }\n }\n}\n","import type {\n Validator,\n StringValidator,\n NumberValidator,\n BooleanValidator,\n EnumValidator,\n ArrayValidator,\n} from './types.js';\nimport { EnvParseError } from '../utils/errors.js';\n\n// Static lookup sets for boolean parsing (shared across all instances)\nconst TRUE_VALUES = new Set(['true', '1', 'yes', 'on']);\nconst FALSE_VALUES = new Set(['false', '0', 'no', 'off']);\n\n// Sentinel symbol for optional missing values\nconst OPTIONAL_MISSING = Symbol('optional');\n\n/**\n * Base validator class with common functionality\n */\nabstract class BaseValidator<T> implements Validator<T> {\n _type!: T;\n _optional = false;\n _default?: T;\n\n abstract parse(value: string | undefined, key: string): T;\n\n optional(): Validator<T | undefined> {\n const clone = this.clone();\n clone._optional = true;\n return clone as Validator<T | undefined>;\n }\n\n default(value: T): Validator<T> {\n const clone = this.clone();\n clone._default = value;\n return clone;\n }\n\n protected abstract clone(): BaseValidator<T>;\n\n protected getRequired(value: string | undefined, key: string): string | symbol {\n if (value === undefined || value === '') {\n if (this._default !== undefined) {\n throw new DefaultValueUsed(this._default);\n }\n if (this._optional) {\n return OPTIONAL_MISSING;\n }\n throw new EnvParseError(key, 'Required environment variable is missing');\n }\n return value;\n }\n}\n\n// Sentinel class for default value (carries the value)\nclass DefaultValueUsed<T> {\n constructor(public readonly value: T) {}\n}\n\n/**\n * String validator implementation\n */\nclass StringValidatorImpl extends BaseValidator<string> implements StringValidator {\n private constraints: Array<(value: string, key: string) => void> = [];\n\n parse(value: string | undefined, key: string): string {\n try {\n const str = this.getRequired(value, key);\n if (str === OPTIONAL_MISSING) return undefined as unknown as string;\n\n for (const constraint of this.constraints) {\n constraint(str as string, key);\n }\n\n return str as string;\n } catch (e) {\n if (e instanceof DefaultValueUsed) return e.value as string;\n throw e;\n }\n }\n\n min(length: number): StringValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value.length < length) {\n throw new EnvParseError(\n key,\n `String must be at least ${length} characters`,\n value\n );\n }\n });\n return clone;\n }\n\n max(length: number): StringValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value.length > length) {\n throw new EnvParseError(\n key,\n `String must be at most ${length} characters`,\n value\n );\n }\n });\n return clone;\n }\n\n url(): StringValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n try {\n new URL(value);\n } catch {\n throw new EnvParseError(key, 'Invalid URL format', value);\n }\n });\n return clone;\n }\n\n email(): StringValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(value)) {\n throw new EnvParseError(key, 'Invalid email format', value);\n }\n });\n return clone;\n }\n\n regex(pattern: RegExp): StringValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (!pattern.test(value)) {\n throw new EnvParseError(\n key,\n `String does not match pattern ${pattern}`,\n value\n );\n }\n });\n return clone;\n }\n\n protected clone(): StringValidatorImpl {\n const clone = new StringValidatorImpl();\n clone._optional = this._optional;\n clone._default = this._default;\n clone.constraints = [...this.constraints];\n return clone;\n }\n}\n\n/**\n * Number validator implementation\n */\nclass NumberValidatorImpl extends BaseValidator<number> implements NumberValidator {\n private constraints: Array<(value: number, key: string) => void> = [];\n\n parse(value: string | undefined, key: string): number {\n try {\n const str = this.getRequired(value, key);\n if (str === OPTIONAL_MISSING) return undefined as unknown as number;\n\n const num = Number(str);\n if (isNaN(num)) {\n throw new EnvParseError(key, 'Invalid number format', str as string);\n }\n\n for (const constraint of this.constraints) {\n constraint(num, key);\n }\n\n return num;\n } catch (e) {\n if (e instanceof DefaultValueUsed) return e.value as number;\n throw e;\n }\n }\n\n min(minValue: number): NumberValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value < minValue) {\n throw new EnvParseError(\n key,\n `Number must be at least ${minValue}`,\n String(value)\n );\n }\n });\n return clone;\n }\n\n max(maxValue: number): NumberValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value > maxValue) {\n throw new EnvParseError(\n key,\n `Number must be at most ${maxValue}`,\n String(value)\n );\n }\n });\n return clone;\n }\n\n int(): NumberValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (!Number.isInteger(value)) {\n throw new EnvParseError(key, 'Number must be an integer', String(value));\n }\n });\n return clone;\n }\n\n positive(): NumberValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value <= 0) {\n throw new EnvParseError(key, 'Number must be positive', String(value));\n }\n });\n return clone;\n }\n\n port(): NumberValidator {\n return this.int().min(1).max(65535);\n }\n\n protected clone(): NumberValidatorImpl {\n const clone = new NumberValidatorImpl();\n clone._optional = this._optional;\n clone._default = this._default;\n clone.constraints = [...this.constraints];\n return clone;\n }\n}\n\n/**\n * Boolean validator implementation\n */\nclass BooleanValidatorImpl extends BaseValidator<boolean> implements BooleanValidator {\n parse(value: string | undefined, key: string): boolean {\n try {\n const str = this.getRequired(value, key);\n if (str === OPTIONAL_MISSING) return undefined as unknown as boolean;\n\n const lower = (str as string).toLowerCase();\n if (TRUE_VALUES.has(lower)) return true;\n if (FALSE_VALUES.has(lower)) return false;\n\n throw new EnvParseError(\n key,\n 'Invalid boolean value. Expected: true, false, 1, 0, yes, no, on, off',\n lower\n );\n } catch (e) {\n if (e instanceof DefaultValueUsed) return e.value as boolean;\n throw e;\n }\n }\n\n protected clone(): BooleanValidatorImpl {\n const clone = new BooleanValidatorImpl();\n clone._optional = this._optional;\n clone._default = this._default;\n return clone;\n }\n}\n\n/**\n * Enum validator implementation\n */\nclass EnumValidatorImpl<T extends string>\n extends BaseValidator<T>\n implements EnumValidator<T>\n{\n constructor(private readonly values: readonly T[]) {\n super();\n }\n\n parse(value: string | undefined, key: string): T {\n try {\n const str = this.getRequired(value, key);\n if (str === OPTIONAL_MISSING) return undefined as unknown as T;\n\n if (!this.values.includes(str as T)) {\n throw new EnvParseError(\n key,\n `Invalid enum value. Expected one of: ${this.values.join(', ')}`,\n str as string\n );\n }\n\n return str as T;\n } catch (e) {\n if (e instanceof DefaultValueUsed) return e.value as T;\n throw e;\n }\n }\n\n protected clone(): EnumValidatorImpl<T> {\n const clone = new EnumValidatorImpl(this.values);\n clone._optional = this._optional;\n clone._default = this._default;\n return clone;\n }\n}\n\n/**\n * Array validator implementation\n */\nclass ArrayValidatorImpl extends BaseValidator<string[]> implements ArrayValidator {\n private sep = ',';\n private constraints: Array<(value: string[], key: string) => void> = [];\n\n parse(value: string | undefined, key: string): string[] {\n try {\n const str = this.getRequired(value, key);\n if (str === OPTIONAL_MISSING) return undefined as unknown as string[];\n\n const arr = (str as string)\n .split(this.sep)\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n for (const constraint of this.constraints) {\n constraint(arr, key);\n }\n\n return arr;\n } catch (e) {\n if (e instanceof DefaultValueUsed) return e.value as string[];\n throw e;\n }\n }\n\n separator(sep: string): ArrayValidator {\n const clone = this.clone();\n clone.sep = sep;\n return clone;\n }\n\n min(length: number): ArrayValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value.length < length) {\n throw new EnvParseError(\n key,\n `Array must have at least ${length} items`,\n value.join(this.sep)\n );\n }\n });\n return clone;\n }\n\n max(length: number): ArrayValidator {\n const clone = this.clone();\n clone.constraints.push((value, key) => {\n if (value.length > length) {\n throw new EnvParseError(\n key,\n `Array must have at most ${length} items`,\n value.join(this.sep)\n );\n }\n });\n return clone;\n }\n\n protected clone(): ArrayValidatorImpl {\n const clone = new ArrayValidatorImpl();\n clone._optional = this._optional;\n clone._default = this._default;\n clone.sep = this.sep;\n clone.constraints = [...this.constraints];\n return clone;\n }\n}\n\n/**\n * Factory functions for creating validators\n */\nexport const validators = {\n string: (): StringValidator => new StringValidatorImpl(),\n number: (): NumberValidator => new NumberValidatorImpl(),\n boolean: (): BooleanValidator => new BooleanValidatorImpl(),\n enum: <T extends string>(values: readonly T[]): EnumValidator<T> =>\n new EnumValidatorImpl(values),\n array: (): ArrayValidator => new ArrayValidatorImpl(),\n};\n","import { readFileSync, existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n/**\n * Parse a .env file and return key-value pairs\n */\nexport function parseEnvFile(filePath: string): Record<string, string> {\n const absolutePath = resolve(process.cwd(), filePath);\n\n if (!existsSync(absolutePath)) {\n return {};\n }\n\n const content = readFileSync(absolutePath, 'utf-8');\n return parseEnvContent(content);\n}\n\n/**\n * Parse .env file content string into key-value pairs\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n const lines = content.split(/\\r?\\n/);\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum]!.trim();\n\n // Skip empty lines and comments\n if (!line || line.startsWith('#')) {\n continue;\n }\n\n // Find the first = sign\n const equalsIndex = line.indexOf('=');\n if (equalsIndex === -1) {\n continue;\n }\n\n const key = line.substring(0, equalsIndex).trim();\n let value = line.substring(equalsIndex + 1).trim();\n\n // Skip if key is empty\n if (!key) {\n continue;\n }\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n // Handle escape sequences in double-quoted strings\n if (line.substring(equalsIndex + 1).trim().startsWith('\"')) {\n value = value\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n }\n } else {\n // Remove inline comments for unquoted values\n const commentIndex = value.indexOf('#');\n if (commentIndex !== -1) {\n value = value.substring(0, commentIndex).trim();\n }\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Load environment variables from a .env file into the current environment\n */\nexport function loadEnvFile(\n filePath = '.env',\n options: { override?: boolean } = {}\n): Record<string, string> {\n const parsed = parseEnvFile(filePath);\n\n for (const [key, value] of Object.entries(parsed)) {\n if (options.override || process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n\n return parsed;\n}\n","import type {\n EnvSchema,\n InferEnv,\n EnvParseOptions,\n EnvValidationError,\n EnvParseResult,\n} from './types.js';\nimport { validators } from './validators.js';\nimport { loadEnvFile, parseEnvFile } from './parser.js';\nimport { EnvValidationException, EnvParseError } from '../utils/errors.js';\n\nexport type { EnvSchema, InferEnv, EnvParseOptions, EnvValidationError, EnvParseResult };\nexport { EnvValidationException, EnvParseError };\n\n/**\n * Create a type-safe environment configuration\n *\n * @example\n * ```typescript\n * import { env } from 'dev-env-toolkit';\n *\n * const config = env.create({\n * PORT: env.number().default(3000),\n * DATABASE_URL: env.string(),\n * NODE_ENV: env.enum(['development', 'production', 'test']),\n * DEBUG: env.boolean().default(false),\n * });\n *\n * // Fully typed!\n * console.log(config.PORT); // number\n * console.log(config.DEBUG); // boolean\n * ```\n */\nfunction create<T extends EnvSchema>(\n schema: T,\n options: EnvParseOptions = {}\n): InferEnv<T> {\n const { path, throwOnError = true, env: customEnv } = options;\n\n // Load .env file if path is provided\n if (path) {\n loadEnvFile(path);\n }\n\n // Use custom env or process.env\n const envSource = customEnv ?? process.env;\n\n const errors: EnvValidationError[] = [];\n const result: Record<string, unknown> = {};\n\n for (const [key, validator] of Object.entries(schema)) {\n try {\n const value = envSource[key];\n result[key] = validator.parse(value, key);\n } catch (error) {\n if (error instanceof EnvParseError) {\n errors.push({\n key: error.key,\n message: error.message.replace(`${error.key}: `, ''),\n value: error.value,\n });\n } else {\n throw error;\n }\n }\n }\n\n if (errors.length > 0 && throwOnError) {\n throw new EnvValidationException(errors);\n }\n\n return result as InferEnv<T>;\n}\n\n/**\n * Safely parse environment variables without throwing\n *\n * @example\n * ```typescript\n * const result = env.safeParse({\n * PORT: env.number(),\n * });\n *\n * if (result.success) {\n * console.log(result.data.PORT);\n * } else {\n * console.error(result.errors);\n * }\n * ```\n */\nfunction safeParse<T extends EnvSchema>(\n schema: T,\n options: Omit<EnvParseOptions, 'throwOnError'> = {}\n): EnvParseResult<InferEnv<T>> {\n const { path, env: customEnv } = options;\n\n // Load .env file if path is provided\n if (path) {\n loadEnvFile(path);\n }\n\n // Use custom env or process.env\n const envSource = customEnv ?? process.env;\n\n const errors: EnvValidationError[] = [];\n const result: Record<string, unknown> = {};\n\n for (const [key, validator] of Object.entries(schema)) {\n try {\n const value = envSource[key];\n result[key] = validator.parse(value, key);\n } catch (error) {\n if (error instanceof EnvParseError) {\n errors.push({\n key: error.key,\n message: error.message.replace(`${error.key}: `, ''),\n value: error.value,\n });\n } else {\n throw error;\n }\n }\n }\n\n if (errors.length > 0) {\n return { success: false, errors };\n }\n\n return { success: true, data: result as InferEnv<T> };\n}\n\n/**\n * The main env object with all utilities\n */\nexport const env = {\n // Schema creation\n create,\n safeParse,\n\n // Validators\n string: validators.string,\n number: validators.number,\n boolean: validators.boolean,\n enum: validators.enum,\n array: validators.array,\n\n // File utilities\n load: loadEnvFile,\n parse: parseEnvFile,\n};\n\nexport default env;\n"]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "dev-env-toolkit",
3
+ "version": "0.1.0",
4
+ "description": "Type-safe environment variables, config management, and debugging utilities for Node.js and TypeScript",
5
+ "author": {
6
+ "name": "Raju Kumar Yadav",
7
+ "email": "notrajuyadav@gmail.com",
8
+ "url": "https://github.com/adhikariraju38"
9
+ },
10
+ "license": "MIT",
11
+ "type": "module",
12
+ "main": "./dist/index.cjs",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "import": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/index.d.cts",
23
+ "default": "./dist/index.cjs"
24
+ }
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "keywords": [
31
+ "env",
32
+ "environment",
33
+ "environment-variables",
34
+ "config",
35
+ "configuration",
36
+ "typescript",
37
+ "type-safe",
38
+ "validation",
39
+ "dotenv",
40
+ "debug",
41
+ "developer-tools"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsup",
45
+ "dev": "tsup --watch",
46
+ "test": "vitest",
47
+ "test:run": "vitest run",
48
+ "test:coverage": "vitest run --coverage",
49
+ "lint": "eslint src tests",
50
+ "typecheck": "tsc --noEmit",
51
+ "prepublishOnly": "npm run build"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.0.6",
55
+ "tsup": "^8.0.0",
56
+ "typescript": "^5.3.0",
57
+ "vitest": "^4.0.16"
58
+ },
59
+ "engines": {
60
+ "node": ">=18.0.0"
61
+ },
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "https://github.com/adhikariraju38/dot-env-toolkit"
65
+ },
66
+ "bugs": {
67
+ "url": "https://github.com/adhikariraju38/dot-env-toolkit/issues"
68
+ },
69
+ "homepage": "https://github.com/adhikariraju38/dot-env-toolkit#readme"
70
+ }