envapt 1.0.4 → 2.0.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 CHANGED
@@ -1,22 +1,25 @@
1
- 'use strict';
2
-
3
- var dotenv = require('dotenv');
1
+ import { config } from 'dotenv';
2
+ import fs from 'fs';
4
3
 
5
4
  var __defProp = Object.defineProperty;
6
5
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
6
 
8
7
  // src/Error.ts
9
- var EnvaptErrorCodes = {
10
- InvalidFallback: 617404,
11
- MissingDelimiter: 967308,
12
- InvalidArrayConverterType: 193159,
13
- InvalidBuiltInConverter: 337271,
14
- InvalidConverterType: 453217,
15
- InvalidCustomConverter: 789432
16
- };
17
- var ReversedEnvaptErrorCodes = Object.fromEntries(
18
- Object.entries(EnvaptErrorCodes).map(([key, value]) => [value, key])
19
- );
8
+ var EnvaptErrorCodes = /* @__PURE__ */ ((EnvaptErrorCodes2) => {
9
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidFallback"] = 101] = "InvalidFallback";
10
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidFallbackType"] = 102] = "InvalidFallbackType";
11
+ EnvaptErrorCodes2[EnvaptErrorCodes2["ArrayFallbackElementTypeMismatch"] = 103] = "ArrayFallbackElementTypeMismatch";
12
+ EnvaptErrorCodes2[EnvaptErrorCodes2["FallbackConverterTypeMismatch"] = 104] = "FallbackConverterTypeMismatch";
13
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidArrayConverterType"] = 201] = "InvalidArrayConverterType";
14
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidBuiltInConverter"] = 202] = "InvalidBuiltInConverter";
15
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidCustomConverter"] = 203] = "InvalidCustomConverter";
16
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidConverterType"] = 204] = "InvalidConverterType";
17
+ EnvaptErrorCodes2[EnvaptErrorCodes2["PrimitiveCoercionFailed"] = 205] = "PrimitiveCoercionFailed";
18
+ EnvaptErrorCodes2[EnvaptErrorCodes2["MissingDelimiter"] = 301] = "MissingDelimiter";
19
+ EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidUserDefinedConfig"] = 302] = "InvalidUserDefinedConfig";
20
+ EnvaptErrorCodes2[EnvaptErrorCodes2["EnvFilesNotFound"] = 303] = "EnvFilesNotFound";
21
+ return EnvaptErrorCodes2;
22
+ })(EnvaptErrorCodes || {});
20
23
  var EnvaptError = class _EnvaptError extends Error {
21
24
  static {
22
25
  __name(this, "EnvaptError");
@@ -24,7 +27,7 @@ var EnvaptError = class _EnvaptError extends Error {
24
27
  code;
25
28
  constructor(code, message) {
26
29
  super(message);
27
- this.name = `${ReversedEnvaptErrorCodes[code]} [${code}]`;
30
+ this.name = `EnvaptError [${code}]`;
28
31
  this.code = code;
29
32
  Error.captureStackTrace(this, _EnvaptError);
30
33
  }
@@ -46,6 +49,28 @@ var ListOfBuiltInConverters = [
46
49
  "date",
47
50
  "time"
48
51
  ];
52
+ var BuiltInConverterTypeCheckers = {
53
+ string: /* @__PURE__ */ __name((value) => typeof value === "string", "string"),
54
+ number: /* @__PURE__ */ __name((value) => typeof value === "number", "number"),
55
+ boolean: /* @__PURE__ */ __name((value) => typeof value === "boolean", "boolean"),
56
+ bigint: /* @__PURE__ */ __name((value) => typeof value === "bigint", "bigint"),
57
+ symbol: /* @__PURE__ */ __name((value) => typeof value === "symbol", "symbol"),
58
+ integer: /* @__PURE__ */ __name((value) => typeof value === "number" && Number.isInteger(value), "integer"),
59
+ float: /* @__PURE__ */ __name((value) => typeof value === "number", "float"),
60
+ json: /* @__PURE__ */ __name((value) => {
61
+ try {
62
+ JSON.parse(JSON.stringify(value));
63
+ return true;
64
+ } catch {
65
+ return false;
66
+ }
67
+ }, "json"),
68
+ array: /* @__PURE__ */ __name((value) => Array.isArray(value), "array"),
69
+ url: /* @__PURE__ */ __name((value) => value instanceof URL, "url"),
70
+ regexp: /* @__PURE__ */ __name((value) => value instanceof RegExp, "regexp"),
71
+ date: /* @__PURE__ */ __name((value) => value instanceof Date, "date"),
72
+ time: /* @__PURE__ */ __name((value) => typeof value === "number", "time")
73
+ };
49
74
 
50
75
  // src/Validators.ts
51
76
  var Validator = class {
@@ -77,16 +102,10 @@ var Validator = class {
77
102
  );
78
103
  return validTypes.includes(value);
79
104
  }
80
- /**
81
- * Check if a value is a valid custom converter function
82
- */
83
- static isValidConverterFunction(converter) {
84
- return typeof converter === "function";
85
- }
86
105
  static customConvertor(converter) {
87
106
  if (typeof converter !== "function") {
88
107
  throw new EnvaptError(
89
- EnvaptErrorCodes.InvalidCustomConverter,
108
+ 203 /* InvalidCustomConverter */,
90
109
  `Custom converter must be a function, got ${typeof converter}.`
91
110
  );
92
111
  }
@@ -96,11 +115,11 @@ var Validator = class {
96
115
  */
97
116
  static arrayConverter(value) {
98
117
  if (!this.isArrayConverter(value)) {
99
- throw new EnvaptError(EnvaptErrorCodes.MissingDelimiter, "Must have delimiter property");
118
+ throw new EnvaptError(301 /* MissingDelimiter */, "Must have delimiter property");
100
119
  }
101
120
  if (value.type !== void 0 && !this.isValidArrayConverterType(value.type)) {
102
121
  throw new EnvaptError(
103
- EnvaptErrorCodes.InvalidArrayConverterType,
122
+ 201 /* InvalidArrayConverterType */,
104
123
  `"${value.type}" is not a valid converter type`
105
124
  );
106
125
  }
@@ -110,15 +129,201 @@ var Validator = class {
110
129
  */
111
130
  static builtInConverter(value) {
112
131
  if (typeof value !== "string") {
113
- throw new EnvaptError(EnvaptErrorCodes.InvalidConverterType, `Expected string, got ${typeof value}`);
132
+ throw new EnvaptError(204 /* InvalidConverterType */, `Expected string, got ${typeof value}`);
114
133
  }
115
134
  if (!ListOfBuiltInConverters.includes(value)) {
116
135
  throw new EnvaptError(
117
- EnvaptErrorCodes.InvalidBuiltInConverter,
136
+ 202 /* InvalidBuiltInConverter */,
118
137
  `"${value}" is not a valid converter type. Valid types are: ${ListOfBuiltInConverters.join(",")}`
119
138
  );
120
139
  }
121
140
  }
141
+ /**
142
+ * Validate that fallback type matches the converter's return type for built-in converters
143
+ */
144
+ static validateBuiltInConverterFallback(converter, fallback) {
145
+ const typeChecker = BuiltInConverterTypeCheckers[converter];
146
+ if (!typeChecker(fallback)) {
147
+ throw new EnvaptError(
148
+ 104 /* FallbackConverterTypeMismatch */,
149
+ `Fallback type does not match converter "${converter}". Expected ${converter} compatible type.`
150
+ );
151
+ }
152
+ }
153
+ /**
154
+ * Validate that all elements in an array fallback have consistent types
155
+ */
156
+ static validateArrayFallbackElementTypes(fallback) {
157
+ if (fallback.length === 0) return;
158
+ const firstElementType = typeof fallback[0];
159
+ const hasInconsistentTypes = fallback.some((element, index) => {
160
+ if (index === 0) return false;
161
+ return typeof element !== firstElementType;
162
+ });
163
+ if (hasInconsistentTypes) {
164
+ throw new EnvaptError(
165
+ 103 /* ArrayFallbackElementTypeMismatch */,
166
+ `All elements in array fallback must have the same type. Found mixed types.`
167
+ );
168
+ }
169
+ }
170
+ /**
171
+ * Validate that array converter type matches fallback element types
172
+ */
173
+ static validateArrayConverterElementTypeMatch(converterType, fallback) {
174
+ if (fallback.length === 0) return;
175
+ const firstElement = fallback[0];
176
+ const typeChecker = BuiltInConverterTypeCheckers[converterType];
177
+ if (!typeChecker(firstElement)) {
178
+ throw new EnvaptError(
179
+ 103 /* ArrayFallbackElementTypeMismatch */,
180
+ `Array converter type "${converterType}" does not match fallback element type. Expected ${converterType} compatible elements.`
181
+ );
182
+ }
183
+ }
184
+ /**
185
+ * Check if a value is a primitive constructor
186
+ */
187
+ static isPrimitiveConstructor(value) {
188
+ return value === String || value === Number || value === Boolean || value === BigInt || value === Symbol;
189
+ }
190
+ /**
191
+ * Safely coerce a fallback value using a primitive constructor
192
+ */
193
+ static coercePrimitiveFallback(converter, fallback) {
194
+ if (this.isCorrectPrimitiveType(converter, fallback)) return fallback;
195
+ return this.performPrimitiveCoercion(converter, fallback);
196
+ }
197
+ /**
198
+ * Check if fallback is already the correct primitive type
199
+ */
200
+ static isCorrectPrimitiveType(converter, fallback) {
201
+ if (converter === String && typeof fallback === "string") return true;
202
+ if (converter === Number && typeof fallback === "number") return true;
203
+ if (converter === Boolean && typeof fallback === "boolean") return true;
204
+ if (converter === BigInt && typeof fallback === "bigint") return true;
205
+ if (converter === Symbol && typeof fallback === "symbol") return true;
206
+ return false;
207
+ }
208
+ /**
209
+ * Perform the actual primitive coercion
210
+ */
211
+ static performPrimitiveCoercion(converter, fallback) {
212
+ try {
213
+ if (converter === String) return String(fallback);
214
+ if (converter === Number) return Number(fallback);
215
+ if (converter === Boolean) return Boolean(fallback);
216
+ if (converter === BigInt) return BigInt(fallback);
217
+ if (converter === Symbol) return Symbol(fallback);
218
+ } catch (error) {
219
+ throw new EnvaptError(
220
+ 205 /* PrimitiveCoercionFailed */,
221
+ `Failed to coerce fallback value using ${converter.name}: ${error.message}`
222
+ );
223
+ }
224
+ throw new EnvaptError(205 /* PrimitiveCoercionFailed */, `Unknown primitive converter: ${converter.name}`);
225
+ }
226
+ /**
227
+ * Make sure the user hasn't provided prohibited options in their dotenv config
228
+ */
229
+ static validateDotenvConfig(config2) {
230
+ if ("path" in config2 || "processEnv" in config2) {
231
+ throw new EnvaptError(
232
+ 302 /* InvalidUserDefinedConfig */,
233
+ 'Custom dotenvConfig should not include "path" or "processEnv" options. Those are managed by Envapter.'
234
+ );
235
+ }
236
+ const validKeys = /* @__PURE__ */ new Set(["encoding", "quiet", "debug", "override", "DOTENV_KEY"]);
237
+ const invalidKeys = Object.keys(config2).filter((key) => !validKeys.has(key));
238
+ if (invalidKeys.length > 0) {
239
+ throw new EnvaptError(
240
+ 302 /* InvalidUserDefinedConfig */,
241
+ `Invalid dotenvConfig options: ${invalidKeys.join(", ")}. Allowed options: ${Array.from(validKeys).join(", ")}`
242
+ );
243
+ }
244
+ return true;
245
+ }
246
+ /**
247
+ * Check if each provided path resolves to an env file by trying to access it
248
+ */
249
+ static validateEnvFilesExist(paths) {
250
+ const missing = paths.filter((p) => {
251
+ try {
252
+ fs.accessSync(p, fs.constants.F_OK);
253
+ return false;
254
+ } catch {
255
+ return true;
256
+ }
257
+ });
258
+ if (missing.length > 0) {
259
+ throw new EnvaptError(
260
+ 303 /* EnvFilesNotFound */,
261
+ `Environment file not found at path: ${missing.join(", ")}`
262
+ );
263
+ }
264
+ }
265
+ };
266
+
267
+ // src/core/EnvapterBase.ts
268
+ var EnvaptCache = /* @__PURE__ */ new Map();
269
+ var EnvapterBase = class _EnvapterBase {
270
+ static {
271
+ __name(this, "EnvapterBase");
272
+ }
273
+ static _envPaths = [".env"];
274
+ // default path
275
+ static _userDefinedDotenvConfig = { quiet: true };
276
+ /**
277
+ * Set custom .env file paths. Accepts either a single path or array of paths.
278
+ * Setting new paths clears the cache and reloads environment variables.
279
+ */
280
+ static set envPaths(paths) {
281
+ const newPaths = Array.isArray(paths) ? paths : [paths];
282
+ Validator.validateEnvFilesExist(newPaths);
283
+ this._envPaths = newPaths;
284
+ this.refreshCache();
285
+ }
286
+ /**
287
+ * Get currently configured .env file paths
288
+ */
289
+ static get envPaths() {
290
+ return this._envPaths;
291
+ }
292
+ /**
293
+ * Set custom dotenv configuration options.
294
+ */
295
+ static set dotenvConfig(config2) {
296
+ Validator.validateDotenvConfig(config2);
297
+ this._userDefinedDotenvConfig = config2;
298
+ this.refreshCache();
299
+ }
300
+ /**
301
+ * Get current dotenv configuration options
302
+ */
303
+ static get dotenvConfig() {
304
+ return this._userDefinedDotenvConfig;
305
+ }
306
+ static refreshCache() {
307
+ EnvaptCache.clear();
308
+ void this.config;
309
+ }
310
+ static get config() {
311
+ if (EnvaptCache.size === 0) {
312
+ const isolatedEnv = { ...process.env };
313
+ try {
314
+ config({ path: this._envPaths, processEnv: isolatedEnv, ...this._userDefinedDotenvConfig });
315
+ } catch {
316
+ }
317
+ for (const [key, value] of Object.entries(isolatedEnv)) EnvaptCache.set(key, value);
318
+ }
319
+ return EnvaptCache;
320
+ }
321
+ /**
322
+ * Get raw environment variable value without parsing or conversion.
323
+ */
324
+ getRaw(key) {
325
+ return _EnvapterBase.config.get(key);
326
+ }
122
327
  };
123
328
 
124
329
  // src/BuiltInConverters.ts
@@ -127,15 +332,13 @@ var BuiltInConverters = class _BuiltInConverters {
127
332
  __name(this, "BuiltInConverters");
128
333
  }
129
334
  static string(raw, fallback) {
130
- return raw ?? fallback;
335
+ return String(raw) || fallback;
131
336
  }
132
337
  static number(raw, fallback) {
133
- if (raw === void 0) return fallback;
134
338
  const parsed = Number(raw);
135
339
  return Number.isNaN(parsed) ? fallback : parsed;
136
340
  }
137
341
  static boolean(raw, fallback) {
138
- if (raw === void 0) return fallback;
139
342
  const lower = raw.toLowerCase().trim();
140
343
  const truthyValues = ["1", "yes", "true", "on"];
141
344
  const falsyValues = ["0", "no", "false", "off"];
@@ -144,7 +347,6 @@ var BuiltInConverters = class _BuiltInConverters {
144
347
  return fallback;
145
348
  }
146
349
  static bigint(raw, fallback) {
147
- if (raw === void 0) return fallback;
148
350
  try {
149
351
  return BigInt(raw);
150
352
  } catch {
@@ -155,17 +357,14 @@ var BuiltInConverters = class _BuiltInConverters {
155
357
  return raw ? Symbol(raw) : fallback;
156
358
  }
157
359
  static integer(raw, fallback) {
158
- if (raw === void 0) return fallback;
159
360
  const parsed = parseInt(raw, 10);
160
361
  return Number.isNaN(parsed) ? fallback : parsed;
161
362
  }
162
363
  static float(raw, fallback) {
163
- if (raw === void 0) return fallback;
164
364
  const parsed = parseFloat(raw);
165
365
  return Number.isNaN(parsed) ? fallback : parsed;
166
366
  }
167
367
  static json(raw, fallback) {
168
- if (raw === void 0) return fallback;
169
368
  try {
170
369
  return JSON.parse(raw);
171
370
  } catch {
@@ -173,12 +372,11 @@ var BuiltInConverters = class _BuiltInConverters {
173
372
  }
174
373
  }
175
374
  static array(raw, fallback, delimiter = ",") {
176
- if (raw === void 0) return fallback;
177
375
  if (raw.trim() === "") return [];
178
- return raw.split(delimiter).map((item) => item.trim()).filter((item) => item.length > 0);
376
+ const arr = raw.split(delimiter).map((item) => item.trim()).filter(Boolean);
377
+ return arr.length ? arr : fallback;
179
378
  }
180
379
  static url(raw, fallback) {
181
- if (raw === void 0) return fallback;
182
380
  try {
183
381
  return new URL(raw);
184
382
  } catch {
@@ -186,7 +384,6 @@ var BuiltInConverters = class _BuiltInConverters {
186
384
  }
187
385
  }
188
386
  static regexp(raw, fallback) {
189
- if (raw === void 0) return fallback;
190
387
  try {
191
388
  const match = raw.match(/^\/(.+)\/([gimsuvy]*)$/);
192
389
  if (match) return new RegExp(match[1], match[2]);
@@ -196,7 +393,6 @@ var BuiltInConverters = class _BuiltInConverters {
196
393
  }
197
394
  }
198
395
  static date(raw, fallback) {
199
- if (raw === void 0) return fallback;
200
396
  if (/^\d+$/.test(raw)) {
201
397
  const timestamp = parseInt(raw, 10);
202
398
  const parsed2 = new Date(timestamp);
@@ -206,13 +402,13 @@ var BuiltInConverters = class _BuiltInConverters {
206
402
  return Number.isNaN(parsed.getTime()) ? fallback : parsed;
207
403
  }
208
404
  static time(raw, fallback) {
209
- if (raw === void 0) return fallback;
210
405
  const match = raw.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/u);
211
406
  if (!match) return fallback;
212
- const [, numStr, unit = "ms"] = match;
407
+ const [, numStr, capturedUnit] = match;
213
408
  if (!numStr) return fallback;
214
409
  const value = Number.parseFloat(numStr);
215
410
  if (Number.isNaN(value)) return fallback;
411
+ const unit = capturedUnit ?? "ms";
216
412
  const SECONDS_TO_MS = 1e3;
217
413
  const SECONDS_PER_MINUTE = 60;
218
414
  const MINUTES_PER_HOUR = 60;
@@ -221,24 +417,18 @@ var BuiltInConverters = class _BuiltInConverters {
221
417
  if (unit === "ms") return value;
222
418
  if (unit === "s") return value * SECONDS_TO_MS;
223
419
  if (unit === "m") return value * MINUTES_TO_MS;
224
- if (unit === "h") return value * HOURS_TO_MS;
225
- return fallback;
420
+ return value * HOURS_TO_MS;
226
421
  }
227
422
  /**
228
423
  * Process array with custom converter config
229
424
  */
230
425
  static processArrayConverter(raw, fallback, config2) {
231
- if (raw === void 0) {
232
- if (Array.isArray(fallback)) return fallback;
233
- throw new EnvaptError(
234
- EnvaptErrorCodes.InvalidFallback,
235
- `ArrayConverter requires that the fallback be an array, got ${typeof fallback}`
236
- );
237
- }
238
426
  if (raw.trim() === "") return [];
239
427
  const items = raw.split(config2.delimiter).map((item) => String(item).trim()).filter(Boolean);
240
- if (!config2.type) return items;
241
- const converter = _BuiltInConverters.getConverter(config2.type);
428
+ if (!items.length) return fallback ? fallback : void 0;
429
+ const type = config2.type;
430
+ if (!type) return items;
431
+ const converter = _BuiltInConverters.getConverter(type);
242
432
  return items.map((item) => {
243
433
  const converted = converter(item, void 0);
244
434
  return converted ?? item;
@@ -263,11 +453,7 @@ var BuiltInConverters = class _BuiltInConverters {
263
453
  date: _BuiltInConverters.date,
264
454
  time: _BuiltInConverters.time
265
455
  };
266
- const converter = converters[type];
267
- if (!Validator.isValidConverterFunction(converter)) {
268
- throw new EnvaptError(EnvaptErrorCodes.InvalidBuiltInConverter, `Unknown built-in converter: ${type}`);
269
- }
270
- return converter;
456
+ return converters[type];
271
457
  }
272
458
  };
273
459
 
@@ -280,12 +466,14 @@ var Parser = class {
280
466
  __name(this, "Parser");
281
467
  }
282
468
  TEMPLATE_REGEX = /\${\w*}/g;
469
+ /**
470
+ * Resolve template variables in a string while handling circular references and missing variables
471
+ * @internal
472
+ */
283
473
  resolveTemplate(key, value, stack = /* @__PURE__ */ new Set()) {
284
- if (stack.has(key)) return value;
285
474
  stack.add(key);
286
475
  const out = value.replace(this.TEMPLATE_REGEX, (template) => {
287
476
  const variable = template.slice(2, -1);
288
- if (!variable) return template;
289
477
  if (stack.has(variable)) return template;
290
478
  const raw = this.envService.getRaw(variable);
291
479
  if (!raw || raw === "") return template;
@@ -297,27 +485,71 @@ var Parser = class {
297
485
  stack.delete(key);
298
486
  return out;
299
487
  }
300
- convertValue(key, fallback, converter, hasFallback = true) {
301
- let resolvedConverter = this.resolveConverter(converter, fallback);
302
- if (resolvedConverter === Number) resolvedConverter = "number";
303
- else if (resolvedConverter === Boolean) resolvedConverter = "boolean";
304
- else if (resolvedConverter === String) resolvedConverter = "string";
305
- else if (resolvedConverter === BigInt) resolvedConverter = "bigint";
306
- else if (resolvedConverter === Symbol) resolvedConverter = "symbol";
488
+ convertValue(key, fallback, converter, hasFallback) {
489
+ const resolvedConverter = this.resolveConverter(converter, fallback);
490
+ const processedFallback = this.processFallbackForConverter(resolvedConverter, fallback);
307
491
  if (Validator.isArrayConverter(resolvedConverter)) {
308
- Validator.arrayConverter(resolvedConverter);
309
- const parsed = this.envService.get(key, void 0);
310
- if (parsed === void 0) return hasFallback ? fallback : null;
311
- return BuiltInConverters.processArrayConverter(parsed, fallback, resolvedConverter);
492
+ return this.processArrayConverter(key, processedFallback, resolvedConverter, hasFallback);
493
+ }
494
+ if (Validator.isPrimitiveConstructor(resolvedConverter)) {
495
+ const stringConverter = this.convertPrimitiveToString(resolvedConverter);
496
+ return this.processBuiltInConverter(key, processedFallback, stringConverter, hasFallback, true);
312
497
  }
313
498
  if (Validator.isBuiltInConverter(resolvedConverter)) {
314
- Validator.builtInConverter(resolvedConverter);
315
- const parsed = this.envService.get(key, void 0);
316
- if (parsed === void 0) return hasFallback ? fallback : null;
317
- const converterFn = BuiltInConverters.getConverter(resolvedConverter);
318
- const result = converterFn(parsed, fallback);
319
- return result;
499
+ return this.processBuiltInConverter(key, processedFallback, resolvedConverter, hasFallback, false);
500
+ }
501
+ return this.processCustomConverter(key, processedFallback, resolvedConverter, hasFallback);
502
+ }
503
+ processFallbackForConverter(converter, fallback) {
504
+ if (Validator.isPrimitiveConstructor(converter) && fallback !== void 0) {
505
+ return Validator.coercePrimitiveFallback(converter, fallback);
506
+ }
507
+ return fallback;
508
+ }
509
+ convertPrimitiveToString(primitiveConstructor) {
510
+ if (primitiveConstructor === String) return "string";
511
+ if (primitiveConstructor === Number) return "number";
512
+ if (primitiveConstructor === Boolean) return "boolean";
513
+ if (primitiveConstructor === BigInt) return "bigint";
514
+ if (primitiveConstructor === Symbol) return "symbol";
515
+ throw new EnvaptError(204 /* InvalidConverterType */, `Unknown primitive constructor`);
516
+ }
517
+ processBuiltInConverter(key, fallback, resolvedConverter, hasFallback, wasOriginallyConstructor) {
518
+ Validator.builtInConverter(resolvedConverter);
519
+ if (hasFallback && fallback !== void 0 && !wasOriginallyConstructor) {
520
+ Validator.validateBuiltInConverterFallback(resolvedConverter, fallback);
521
+ if (resolvedConverter === "array" && Array.isArray(fallback)) {
522
+ Validator.validateArrayFallbackElementTypes(fallback);
523
+ }
320
524
  }
525
+ const parsed = this.envService.get(key, void 0);
526
+ if (parsed === void 0) return hasFallback ? fallback : null;
527
+ const converterFn = BuiltInConverters.getConverter(resolvedConverter);
528
+ const result = converterFn(parsed, fallback);
529
+ if (result === void 0 && !hasFallback) return null;
530
+ return result;
531
+ }
532
+ processArrayConverter(key, fallback, resolvedConverter, hasFallback) {
533
+ Validator.arrayConverter(resolvedConverter);
534
+ if (hasFallback && fallback !== void 0 && !Array.isArray(fallback)) {
535
+ throw new EnvaptError(
536
+ 101 /* InvalidFallback */,
537
+ `ArrayConverter requires that the fallback be an array, got ${typeof fallback}`
538
+ );
539
+ }
540
+ if (hasFallback && Array.isArray(fallback)) {
541
+ Validator.validateArrayFallbackElementTypes(fallback);
542
+ if (resolvedConverter.type) {
543
+ Validator.validateArrayConverterElementTypeMatch(resolvedConverter.type, fallback);
544
+ }
545
+ }
546
+ const parsed = this.envService.get(key, void 0);
547
+ if (parsed === void 0) return hasFallback ? fallback : null;
548
+ const result = BuiltInConverters.processArrayConverter(parsed, fallback, resolvedConverter);
549
+ if (result === void 0 && !hasFallback) return null;
550
+ return result;
551
+ }
552
+ processCustomConverter(key, fallback, resolvedConverter, hasFallback) {
321
553
  Validator.customConvertor(resolvedConverter);
322
554
  const raw = this.envService.get(key, void 0);
323
555
  if (raw === void 0) return hasFallback ? fallback : null;
@@ -334,253 +566,230 @@ var Parser = class {
334
566
  }
335
567
  };
336
568
 
337
- // src/Envapter.ts
338
- var EnvaptCache = /* @__PURE__ */ new Map();
569
+ // src/core/EnvironmentMethods.ts
339
570
  var Environment = /* @__PURE__ */ ((Environment2) => {
340
571
  Environment2[Environment2["Development"] = 0] = "Development";
341
572
  Environment2[Environment2["Staging"] = 1] = "Staging";
342
573
  Environment2[Environment2["Production"] = 2] = "Production";
343
574
  return Environment2;
344
575
  })(Environment || {});
345
- var Envapter = class _Envapter {
576
+ var EnvironmentMethods = class _EnvironmentMethods extends EnvapterBase {
346
577
  static {
347
- __name(this, "Envapter");
578
+ __name(this, "EnvironmentMethods");
348
579
  }
349
- static parser = new Parser(new _Envapter());
350
- static _envPaths = [".env"];
351
- // default path
352
- // Environment handling
353
- static internalEnvironment = this.determineEnvironment(
354
- this.get("ENVIRONMENT", this.get("ENV", this.get("NODE_ENV", "development")))
355
- );
356
- /**
357
- * Set custom .env file paths. Accepts either a single path or array of paths.
358
- * Setting new paths clears the cache and reloads environment variables.
359
- *
360
- * @param paths - Single file path or array of file paths to load
361
- *
362
- * @example
363
- * ```ts
364
- * // Single file
365
- * Envapter.envPaths = '.env.production';
366
- *
367
- * // Multiple files (loaded in order)
368
- * Envapter.envPaths = ['.env', '.env.local', '.env.production'];
369
- * ```
370
- */
371
- static set envPaths(paths) {
372
- this._envPaths = Array.isArray(paths) ? paths : [paths];
373
- EnvaptCache.clear();
374
- void this.config;
375
- this.internalEnvironment = this.determineEnvironment(
376
- this.get("ENVIRONMENT", this.get("ENV", this.get("NODE_ENV", "development")))
377
- );
580
+ static _environment;
581
+ static determineEnvironment(env) {
582
+ const environment = env ?? this.getRawValue("ENVIRONMENT", this.getRawValue("ENV", this.getRawValue("NODE_ENV", "development")));
583
+ if (typeof environment === "string") {
584
+ this._environment = environment.toLowerCase() === "production" ? 2 /* Production */ : environment === "staging" ? 1 /* Staging */ : 0 /* Development */;
585
+ } else {
586
+ this._environment = environment;
587
+ }
588
+ }
589
+ static getRawValue(key, fallback) {
590
+ return this.config.get(key) || fallback;
378
591
  }
379
592
  /**
380
- * Get currently configured .env file paths
381
- * @returns Array of file paths being loaded
593
+ * Get the current application environment
382
594
  */
383
- static get envPaths() {
384
- return this._envPaths;
385
- }
386
- static determineEnvironment(env) {
387
- if (typeof env === "string") {
388
- switch (env.toLowerCase()) {
389
- case "production":
390
- return 2 /* Production */;
391
- case "staging":
392
- return 1 /* Staging */;
393
- default:
394
- return 0 /* Development */;
395
- }
595
+ static get environment() {
596
+ if (this._environment === void 0) {
597
+ this.determineEnvironment();
396
598
  }
397
- return env;
599
+ return this._environment;
398
600
  }
399
601
  /**
400
602
  * Set the application environment. Accepts either Environment enum or string value.
401
- *
402
- * @param env - Environment value ('development', 'staging', 'production') or Environment enum
403
- *
404
- * @example
405
- * ```ts
406
- * Envapter.environment = Environment.Production;
407
- * Envapter.environment = 'staging';
408
- * ```
409
603
  */
410
604
  static set environment(env) {
411
- this.internalEnvironment = this.determineEnvironment(env);
605
+ this.determineEnvironment(env);
412
606
  }
413
607
  /**
414
- * Get the current application environment
415
- * @returns Current environment enum value
608
+ * @see {@link EnvironmentMethods.environment}
416
609
  */
417
- static get environment() {
418
- return this.internalEnvironment;
610
+ get environment() {
611
+ return _EnvironmentMethods.environment;
612
+ }
613
+ /**
614
+ * @see {@link EnvironmentMethods.environment}
615
+ */
616
+ set environment(env) {
617
+ _EnvironmentMethods.determineEnvironment(env);
419
618
  }
420
619
  /**
421
620
  * Check if the current environment is production
422
- * @returns true if environment is production
423
621
  */
424
622
  static get isProduction() {
425
- return this.internalEnvironment === 2 /* Production */;
623
+ return this.environment === 2 /* Production */;
624
+ }
625
+ /**
626
+ * @see {@link EnvironmentMethods.isProduction}
627
+ */
628
+ get isProduction() {
629
+ return _EnvironmentMethods.environment === 2 /* Production */;
426
630
  }
427
631
  /**
428
632
  * Check if the current environment is staging
429
- * @returns true if environment is staging
430
633
  */
431
634
  static get isStaging() {
432
- return this.internalEnvironment === 1 /* Staging */;
635
+ return this.environment === 1 /* Staging */;
636
+ }
637
+ /**
638
+ * @see {@link EnvironmentMethods.isStaging}
639
+ */
640
+ get isStaging() {
641
+ return _EnvironmentMethods.environment === 1 /* Staging */;
433
642
  }
434
643
  /**
435
644
  * Check if the current environment is development
436
- * @returns true if environment is development
437
645
  */
438
646
  static get isDevelopment() {
439
- return this.internalEnvironment === 0 /* Development */;
647
+ return this.environment === 0 /* Development */;
440
648
  }
441
- static get config() {
442
- if (EnvaptCache.size === 0) {
443
- const isolatedEnv = { ...process.env };
444
- try {
445
- dotenv.config({ path: this._envPaths, quiet: true, processEnv: isolatedEnv });
446
- } catch {
447
- }
448
- for (const [key, value] of Object.entries(isolatedEnv)) EnvaptCache.set(key, value);
449
- }
450
- return EnvaptCache;
649
+ /**
650
+ * @see {@link EnvironmentMethods.isDevelopment}
651
+ */
652
+ get isDevelopment() {
653
+ return _EnvironmentMethods.environment === 0 /* Development */;
654
+ }
655
+ static refreshCache() {
656
+ super.refreshCache();
657
+ this._environment = void 0;
658
+ }
659
+ };
660
+
661
+ // src/core/PrimitiveMethods.ts
662
+ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
663
+ static {
664
+ __name(this, "PrimitiveMethods");
451
665
  }
452
- static _get(key, type = 0 /* String */, def) {
666
+ static parser = new Parser(new _PrimitiveMethods());
667
+ static _get(key, type, def) {
453
668
  const rawVal = this.config.get(key);
454
669
  if (!rawVal) return def;
455
670
  const parsed = this.parser.resolveTemplate(key, String(rawVal));
456
- switch (type) {
457
- case 0 /* String */: {
458
- return BuiltInConverters.string(parsed, def);
459
- }
460
- case 1 /* Number */: {
461
- return BuiltInConverters.number(parsed, def);
462
- }
463
- case 2 /* Boolean */: {
464
- return BuiltInConverters.boolean(parsed, def);
465
- }
466
- case 3 /* BigInt */: {
467
- return BuiltInConverters.bigint(parsed, def);
468
- }
469
- case 4 /* Symbol */: {
470
- return BuiltInConverters.symbol(parsed, def);
471
- }
472
- default: {
473
- return BuiltInConverters.string(parsed, def);
474
- }
475
- }
671
+ let result;
672
+ if (type === 1 /* Number */) result = BuiltInConverters.number(parsed, def);
673
+ else if (type === 2 /* Boolean */) result = BuiltInConverters.boolean(parsed, def);
674
+ else if (type === 3 /* BigInt */) result = BuiltInConverters.bigint(parsed, def);
675
+ else if (type === 4 /* Symbol */) result = BuiltInConverters.symbol(parsed, def);
676
+ else result = BuiltInConverters.string(parsed, def);
677
+ return result;
476
678
  }
477
679
  /**
478
680
  * Get a string environment variable with optional fallback.
479
681
  * Supports template variable resolution using ${VAR} syntax.
480
- *
481
- * @param key - Environment variable name
482
- * @param def - Default value if variable is not found
483
- * @returns The environment variable value or default
484
- *
485
- * @example
486
- * ```ts
487
- * const apiUrl = Envapter.get('API_URL', 'http://localhost:3000');
488
- * ```
489
682
  */
490
683
  static get(key, def) {
491
684
  return this._get(key, 0 /* String */, def);
492
685
  }
686
+ /**
687
+ * @see {@link PrimitiveMethods.get}
688
+ */
689
+ get(key, def) {
690
+ return _PrimitiveMethods._get(key, 0 /* String */, def);
691
+ }
493
692
  /**
494
693
  * Get a number environment variable with optional fallback.
495
694
  * Automatically converts string values to numbers.
496
- *
497
- * @param key - Environment variable name
498
- * @param def - Default value if variable is not found or cannot be converted
499
- * @returns The environment variable value as number or default
500
- *
501
- * @example
502
- * ```ts
503
- * const port = Envapter.getNumber('PORT', 3000);
504
- * ```
505
695
  */
506
696
  static getNumber(key, def) {
507
697
  return this._get(key, 1 /* Number */, def);
508
698
  }
699
+ /**
700
+ * @see {@link PrimitiveMethods.getNumber}
701
+ */
702
+ getNumber(key, def) {
703
+ return _PrimitiveMethods._get(key, 1 /* Number */, def);
704
+ }
509
705
  /**
510
706
  * Get a boolean environment variable with optional fallback.
511
- * Recognizes: `1`, `yes`, `true` as **true**; `0`, `no`, `false` as **false** (case-insensitive).
512
- *
513
- * @param key - Environment variable name
514
- * @param def - Default value if variable is not found or cannot be converted
515
- * @returns The environment variable value as boolean or default
516
- *
517
- * @example
518
- * ```ts
519
- * const isProduction = Envapter.getBoolean('IS_PRODUCTION', false);
520
- * ```
707
+ * Recognizes: `1`, `yes`, `true`, 'on' as **true**; `0`, `no`, `false`, 'off' as **false** (case-insensitive).
521
708
  */
522
709
  static getBoolean(key, def) {
523
710
  return this._get(key, 2 /* Boolean */, def);
524
711
  }
712
+ /**
713
+ * @see {@link PrimitiveMethods.getBoolean}
714
+ */
715
+ getBoolean(key, def) {
716
+ return _PrimitiveMethods._get(key, 2 /* Boolean */, def);
717
+ }
525
718
  /**
526
719
  * Get a bigint environment variable with optional fallback.
527
720
  * Automatically converts string values to bigint.
528
- *
529
- * @param key - Environment variable name
530
- * @param def - Default value if variable is not found or cannot be converted
531
- * @returns The environment variable value as bigint or default
532
- *
533
- * @example
534
- * ```ts
535
- * const largeNumber = Envapter.getBigInt('LARGE_NUMBER', 123456789012345678901234567890n);
536
- * ```
537
721
  */
538
722
  static getBigInt(key, def) {
539
723
  return this._get(key, 3 /* BigInt */, def);
540
724
  }
725
+ /**
726
+ * @see {@link PrimitiveMethods.getBigInt}
727
+ */
728
+ getBigInt(key, def) {
729
+ return _PrimitiveMethods._get(key, 3 /* BigInt */, def);
730
+ }
541
731
  /**
542
732
  * Get a symbol environment variable with optional fallback.
543
733
  * Creates a symbol from the string value.
544
- *
545
- * @param key - Environment variable name
546
- * @param def - Default value if variable is not found
547
- * @returns The environment variable value as symbol or default
548
- *
549
- * @example
550
- * ```ts
551
- * const uniqueKey = Envapter.getSymbol('UNIQUE_KEY', Symbol('default'));
552
- * ```
553
734
  */
554
735
  static getSymbol(key, def) {
555
736
  return this._get(key, 4 /* Symbol */, def);
556
737
  }
557
- get(key, def) {
558
- return _Envapter._get(key, 0 /* String */, def);
738
+ /**
739
+ * @see {@link PrimitiveMethods.getSymbol}
740
+ */
741
+ getSymbol(key, def) {
742
+ return _PrimitiveMethods._get(key, 4 /* Symbol */, def);
559
743
  }
560
- getNumber(key, def) {
561
- return _Envapter._get(key, 1 /* Number */, def);
744
+ };
745
+
746
+ // src/core/AdvancedMethods.ts
747
+ var AdvancedMethods = class _AdvancedMethods extends PrimitiveMethods {
748
+ static {
749
+ __name(this, "AdvancedMethods");
562
750
  }
563
- getBoolean(key, def) {
564
- return _Envapter._get(key, 2 /* Boolean */, def);
751
+ static getUsing(key, converter, fallback) {
752
+ const rawVal = this.config.get(key);
753
+ if (!rawVal) return fallback;
754
+ const hasFallback = fallback !== void 0;
755
+ const result = this.parser.convertValue(key, fallback, converter, hasFallback);
756
+ return result;
565
757
  }
566
- getBigInt(key, def) {
567
- return _Envapter._get(key, 3 /* BigInt */, def);
758
+ getUsing(key, converter, fallback) {
759
+ return _AdvancedMethods.getUsing(key, converter, fallback);
568
760
  }
569
- getSymbol(key, def) {
570
- return _Envapter._get(key, 4 /* Symbol */, def);
761
+ /**
762
+ * Get an environment variable using a custom converter function.
763
+ */
764
+ static getWith(key, converter, fallback) {
765
+ const rawVal = this.config.get(key);
766
+ if (!rawVal) return fallback;
767
+ const hasFallback = fallback !== void 0;
768
+ const result = this.parser.convertValue(
769
+ key,
770
+ fallback,
771
+ converter,
772
+ hasFallback
773
+ );
774
+ return result;
571
775
  }
572
776
  /**
573
- * Get raw environment variable value without parsing or conversion.
574
- *
575
- * @internal
777
+ * @see {@link AdvancedMethods.getWith}
576
778
  */
577
- getRaw(key) {
578
- return _Envapter.config.get(key);
779
+ getWith(key, converter, fallback) {
780
+ return _AdvancedMethods.getWith(key, converter, fallback);
781
+ }
782
+ };
783
+
784
+ // src/Envapter.ts
785
+ var Envapter = class extends AdvancedMethods {
786
+ static {
787
+ __name(this, "Envapter");
579
788
  }
580
789
  };
581
790
 
582
791
  // src/Envapt.ts
583
- function createPropertyDecorator(key, fallback, converter, hasFallback = true) {
792
+ function createPropertyDecorator(key, fallback, converter, hasFallback) {
584
793
  return function(target, prop) {
585
794
  const propKey = String(prop);
586
795
  const cacheKey = `${target.constructor.name}.${propKey}`;
@@ -618,8 +827,24 @@ function Envapt(key, fallbackOrOptions, converter) {
618
827
  }
619
828
  __name(Envapt, "Envapt");
620
829
 
621
- exports.Envapt = Envapt;
622
- exports.Envapter = Envapter;
623
- exports.Environment = Environment;
830
+ // src/Converters.ts
831
+ var Converters = /* @__PURE__ */ ((Converters2) => {
832
+ Converters2["String"] = "string";
833
+ Converters2["Number"] = "number";
834
+ Converters2["Boolean"] = "boolean";
835
+ Converters2["Bigint"] = "bigint";
836
+ Converters2["Symbol"] = "symbol";
837
+ Converters2["Integer"] = "integer";
838
+ Converters2["Float"] = "float";
839
+ Converters2["Json"] = "json";
840
+ Converters2["Array"] = "array";
841
+ Converters2["Url"] = "url";
842
+ Converters2["Regexp"] = "regexp";
843
+ Converters2["Date"] = "date";
844
+ Converters2["Time"] = "time";
845
+ return Converters2;
846
+ })(Converters || {});
847
+
848
+ export { Converters, Envapt, EnvaptErrorCodes, Envapter, Environment };
624
849
  //# sourceMappingURL=index.js.map
625
850
  //# sourceMappingURL=index.js.map