envapt 1.1.0 โ†’ 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/README.md CHANGED
@@ -1,67 +1,128 @@
1
- # Envapt - The apt way to handle env
2
-
3
- A powerful TypeScript-first environment configuration library that provides type detection, template variable resolution, and decorator-based class property configuration by extending dotenv.
4
-
5
- ## Features
6
-
7
- - ๐Ÿ”ง **Automatic Type Detection** - Types inferred from fallback values
1
+ <p align="center">
2
+ <img src="assets/banner.png" alt="Envapt โ€“ The apt way to handle environment variables" width="100%" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ A TypeScript environment configuration library that eliminates the boilerplate of parsing <code>.env</code> files.<br/>
7
+ Get environment variables with correct runtime typing and fallbacks, template support, and automatic, built-in, & custom transformations.<br/>
8
+ <strong>No more <code>process.env.PORT || '3000'</code> everywhere!</strong>
9
+ </p>
10
+
11
+ <div align="center">
12
+ <a href="https://github.com/materwelondhruv/envapt/actions"><img alt="Build" src="https://img.shields.io/github/actions/workflow/status/materwelondhruv/envapt/publish.yml?branch=main&label=build&style=flat-square&color=0d1117&logo=github"></a>
13
+ <a href="https://app.codecov.io/gh/materwelondhruv/envapt"><img alt="Coverage" src="https://img.shields.io/codecov/c/github/materwelondhruv/envapt?style=flat-square&color=f01f7a&logo=codecov"></a>
14
+ <a href="https://www.npmjs.com/package/envapt"><img alt="npm version" src="https://img.shields.io/npm/v/envapt?style=flat-square&color=cb3838&logo=npm"></a>
15
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/npm/l/envapt?style=flat-square&color=e97826&logo=apache"></a>
16
+ <a href="https://www.typescriptlang.org/"><img alt="Types" src="https://img.shields.io/badge/types-TypeScript-3178c6?style=flat-square&logo=typescript&logoColor=white"></a>
17
+ <a href="https://nodejs.org/api/esm.html"><img alt="ESM" src="https://img.shields.io/badge/ESM-Supported-ffca28?style=flat-square"></a>
18
+ <a href="https://nodejs.org/api/modules.html"><img alt="CJS" src="https://img.shields.io/badge/CJS-Supported-ff6b35?style=flat-square"></a>
19
+ <a href="https://nodejs.org/"><img alt="Node" src="https://img.shields.io/badge/node-%3E=22.0.0-339933?style=flat-square&logo=node.js&logoColor=white"></a>
20
+ <a href="https://bundlephobia.com/package/envapt"><img alt="Bundle Size" src="https://img.shields.io/bundlephobia/minzip/envapt?style=flat-square&color=success"></a>
21
+ <a href="https://www.npmjs.com/package/envapt"><img alt="Downloads" src="https://img.shields.io/npm/dm/envapt?style=flat-square&color=blue"></a>
22
+ <a href="https://github.com/materwelondhruv/envapt"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/materwelondhruv/envapt?style=flat-square&color=yellow"></a>
23
+ </div>
24
+
25
+ ---
26
+
27
+ ## โœจ Features
28
+
29
+ - ๐Ÿ”ง **Automatic Type Detection** - Runtime types inferred from fallback values
8
30
  - ๐Ÿ”— **Template Variables** - `${VAR}` syntax with circular reference protection
9
- - ๐ŸŽฏ **Class Properties** - Decorator-based configuration for class members
31
+ - ๐ŸŽฏ **Class Properties** - Functional and Decorator-based configuration for class members
10
32
  - ๐Ÿท๏ธ **Built-in & Custom Converters** - Ready-to-use converters for common patterns + custom transformations
11
33
  - ๐ŸŒ **Environment Detection** - Built-in development/staging/production handling
12
34
  - ๐Ÿ“‚ **Multiple .env Files** - Load from multiple sources
13
- - ๐Ÿ’ช **Edge Case Handling** - Robust parsing for all scenarios
35
+ - ๐Ÿ’ช **Edge Case Handling** - Robust validation and parsing for all scenarios
14
36
  - ๐Ÿ›ก๏ธ **Type Safety** - Full TypeScript support with proper type inference
37
+ - โšก **Lightweight** - Minimal overhead with [`dotenv`](https://www.npmjs.com/package/dotenv) bundled
15
38
 
16
- ## Table of Contents
39
+ ---
40
+
41
+ ## ๐Ÿ“š Table of Contents
42
+
43
+ ### โš™๏ธ Essentials
17
44
 
18
45
  - [Requirements](#requirements)
19
46
  - [Quick Start](#quick-start)
20
47
  - [Installation](#installation)
21
48
  - [Basic Usage](#basic-usage)
49
+
50
+ ### ๐Ÿงฌ API Reference
51
+
22
52
  - [API Reference](#api-reference)
23
53
  - [Decorator API](#decorator-api)
24
- - [Built-in Converters](#built-in-converters)
25
- - [Custom Array Converters](#custom-array-converters)
26
- - [Custom Converters](#custom-converters)
27
- - [Handling Missing Values](#handling-missing-values)
54
+ - [Modern Syntax (Recommended)](#modern-syntax-recommended)
55
+ - [Classic Syntax](#classic-syntax)
56
+ - [Automatic Runtime Type Detection](#automatic-runtime-type-detection)
57
+ - [Primitive Converters](#primitive-converters)
58
+ - [Built-in Converters](#built-in-converters)
59
+ - [Custom Array Converters](#custom-array-converters)
60
+ - [Custom Converters](#custom-converters)
61
+ - [Handling Missing Values](#handling-missing-values)
28
62
  - [Functional API](#functional-api)
63
+ - [Converter Type Quick Reference](#converter-type-quick-reference)
64
+
65
+ ### ๐ŸŒ Environment & Templates
66
+
29
67
  - [Environment Detection](#environment-detection)
68
+ - [Environment Management](#environment-management)
30
69
  - [Template Variables](#template-variables)
70
+ - [Circular Reference Protection](#circular-reference-protection)
71
+
72
+ ### ๐Ÿ›  Configuration & Errors
73
+
74
+ - [Configuration](#configuration)
75
+ - [Multiple .env Files](#multiple-env-files)
76
+ - [Dotenv Configuration](#dotenv-configuration)
77
+ - [Error Handling](#error-handling)
78
+ - [Error Code Reference](#error-code-reference)
79
+
80
+ ### ๐Ÿš€ Examples
81
+
31
82
  - [Advanced Examples](#advanced-examples)
83
+ - [Complex Configuration](#complex-configuration)
84
+
85
+ ---
32
86
 
33
87
  ## Requirements
34
88
 
35
- - **Node.js**: v22 or later (recommended for ESM and nodenext support)
36
- - **TypeScript**: v5.8 or later
37
- - **Dependencies**:
38
- - `dotenv` (runtime dependency | bundled)
39
- - **TypeScript Compiler Options**:
40
- - `experimentalDecorators: true`
41
- - `module: nodenext OR esnext`
42
- - `moduleResolution: nodenext OR bundler`
43
- - `target: ESnext`
44
- - `lib: ESNext`
45
- - **ESM Support**: Project uses ESM, so your environment and tooling should support ES modules.
89
+ #### ๐ŸŸข Runtime
46
90
 
47
- ## Quick Start
91
+ - **Node.js**: `>=22.0.0`
92
+ _Recommended for full ESM and `nodenext` support_
48
93
 
49
- ### Installation
94
+ - **TypeScript**: `>=5.8`
50
95
 
51
- ```bash
52
- # npm
53
- npm install envapt
96
+ #### ๐Ÿ“ฆ Runtime Dependency
54
97
 
55
- # pnpm
56
- pnpm add envapt
98
+ - **dotenv**: _(bundled at runtime)_
57
99
 
58
- # yarn
59
- yarn add envapt
100
+ #### ๐Ÿ› ๏ธ TypeScript Compiler Options
101
+
102
+ ```jsonc
103
+ // tsconfig.json (required settings)
104
+ {
105
+ "experimentalDecorators": true,
106
+ "module": "esnext", // or "nodenext"
107
+ "moduleResolution": "bundler", // or "nodenext"
108
+ "target": "ESNext",
109
+ "lib": ["ESNext"]
110
+ }
60
111
  ```
61
112
 
113
+ ## Quick Start
114
+
115
+ ### Installation
116
+
117
+ | Package Manager | Command |
118
+ | --------------- | -------------------- |
119
+ | **npm** | `npm install envapt` |
120
+ | **pnpm** | `pnpm add envapt` |
121
+ | **yarn** | `yarn add envapt` |
122
+
62
123
  ### Basic Usage
63
124
 
64
- Create a `.env` file:
125
+ **Step 1:** Create a `.env` file:
65
126
 
66
127
  ```env
67
128
  APP_PORT=8443
@@ -72,22 +133,22 @@ MAX_CONNECTIONS=100
72
133
  ALLOWED_ORIGINS=https://app.com,https://admin.com
73
134
  ```
74
135
 
75
- Use with decorators (recommended):
136
+ Use with decorators:
76
137
 
77
138
  ```ts
78
- import { Envapt, Envapter } from 'envapt';
139
+ import { Envapt, Envapter, Converters } from 'envapt';
79
140
 
80
141
  // Global app configuration (static properties)
81
142
  class AppConfig extends Envapter {
82
143
  @Envapt('APP_PORT', 3000)
83
144
  static readonly port: number;
84
145
 
85
- @Envapt('APP_URL', 'http://localhost:3000', 'url')
146
+ @Envapt('APP_URL', 'http://localhost:3000', Converters.Url)
86
147
  static readonly url: URL;
87
148
 
88
149
  @Envapt('ALLOWED_ORIGINS', {
89
150
  fallback: ['http://localhost:3000'],
90
- converter: 'array'
151
+ converter: Converters.Array
91
152
  })
92
153
  static readonly allowedOrigins: string[];
93
154
  }
@@ -97,10 +158,10 @@ class DatabaseService {
97
158
  @Envapt('DATABASE_URL', 'sqlite://memory')
98
159
  declare readonly databaseUrl: string;
99
160
 
100
- @Envapt('MAX_CONNECTIONS', { converter: 'number', fallback: 10 })
161
+ @Envapt('MAX_CONNECTIONS', { converter: Converters.Number, fallback: 10 })
101
162
  declare readonly maxConnections: number;
102
163
 
103
- @Envapt('REQUEST_TIMEOUT', { converter: 'time', fallback: 5000 })
164
+ @Envapt('REQUEST_TIMEOUT', { converter: Converters.Time, fallback: 5000 })
104
165
  declare readonly timeout: number; // Converts "5s" to 5000ms
105
166
 
106
167
  async connect() {
@@ -117,8 +178,7 @@ const dbService = new DatabaseService();
117
178
  await dbService.connect();
118
179
  ```
119
180
 
120
- Or use functionally:\
121
- <sub>Limited to primitives, String, Number, Boolean, Symbol, and BigInt. Does not support converters.</sub>
181
+ Or use functionally:
122
182
 
123
183
  ```ts
124
184
  import { Envapter } from 'envapt';
@@ -151,9 +211,9 @@ The `@Envapt` decorator can be used on both **static** and **instance** class pr
151
211
  @Envapt('ENV_VAR', fallback?, converter?)
152
212
  ```
153
213
 
154
- #### Automatic Type Detection
214
+ #### Automatic Runtime Type Detection
155
215
 
156
- Types are automatically inferred from fallback values. Use static properties for app-wide config and instance properties for service-specific config:
216
+ Types are automatically inferred from fallback values.
157
217
 
158
218
  ```ts
159
219
  class Config extends Envapter {
@@ -183,65 +243,144 @@ class Config extends Envapter {
183
243
  }
184
244
  ```
185
245
 
246
+ #### Primitive Converters
247
+
248
+ Envapt allows using the 5 "primitive" type-like converters. These **will** coerce values.
249
+
250
+ > [!NOTE]
251
+ > The runtime validator will ignore this usage, allowing type coercion for flexibility.
252
+
253
+ **Valid Primitive Types:** `String`, `Number`, `Boolean`, `Symbol`, and `BigInt`.
254
+
255
+ ```ts
256
+ class Config extends Envapter {
257
+ @Envapt('PORT_STRING', { fallback: 'hello-world', converter: String })
258
+ static readonly portAsString: string;
259
+
260
+ @Envapt('DEBUG_FLAG', { fallback: true, converter: Boolean })
261
+ static readonly debugMode: boolean;
262
+
263
+ @Envapt('USER_ID', { fallback: 12345, converter: Number })
264
+ static readonly userId: number;
265
+
266
+ @Envapt('MAX_SAFE_INT', { fallback: 9007199254740991n, converter: BigInt })
267
+ static readonly maxSafeInt: bigint;
268
+
269
+ @Envapt('APP_INSTANCE', { fallback: Symbol(main), converter: Symbol })
270
+ static readonly appInstance: symbol;
271
+
272
+ // Instance properties work the same way
273
+ @Envapt('CONNECTION_TIMEOUT', { fallback: 5000, converter: Number })
274
+ declare readonly timeout: number;
275
+
276
+ // Type coercion example
277
+ @Envapt('PERMISSIONS', { fallback: '72394823472342983', converter: BigInt })
278
+ declare readonly permissions: bigint; // Converts "72394823472342983" to BigInt
279
+ }
280
+ ```
281
+
282
+ **When to use primitive converters:**
283
+
284
+ - When you need explicit type coercion between incompatible types
285
+ - When working with external systems that provide values in unexpected formats
286
+
186
287
  #### Built-in Converters
187
288
 
188
289
  Envapt provides many built-in converters for common patterns:
189
290
 
291
+ > [!IMPORTANT]
292
+ > **Use the `Converters` enum** instead of string literals. They look better, and provide better type inference:
293
+ >
294
+ > ```ts
295
+ > import { Converters } from 'envapt';
296
+ > // โœ… Recommended: Use enum
297
+ > @Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
298
+ >
299
+ > // โŒ Discouraged: String literals (still supported for compatibility)
300
+ > @Envapt('PORT', { converter: 'number', fallback: 3000 })
301
+ > ```
302
+
303
+ > [!IMPORTANT]
304
+ > Built-in converters enforce **strict type validation** between the converter and fallback types. The converter's expected return type must match the fallback's type.
305
+
190
306
  ```ts
191
307
  class Config extends Envapter {
192
308
  // Basic types
193
- @Envapt('APP_NAME', { converter: 'string', fallback: 'MyApp' })
309
+ @Envapt('APP_NAME', { converter: Converters.String, fallback: 'MyApp' })
194
310
  static readonly appName: string;
195
311
 
196
- @Envapt('PORT', { converter: 'number', fallback: 3000 })
312
+ @Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
197
313
  static readonly port: number;
198
314
 
199
- @Envapt('PRODUCTION_MODE', { converter: 'boolean', fallback: false })
315
+ @Envapt('PRODUCTION_MODE', { converter: Converters.Boolean, fallback: false })
200
316
  static readonly productionMode: boolean;
201
317
 
202
318
  // Advanced types
203
- @Envapt('CORS_ORIGINS', { converter: 'array', fallback: [] })
319
+ @Envapt('CORS_ORIGINS', { converter: Converters.Array, fallback: [] })
204
320
  static readonly corsOrigins: string[];
205
321
 
206
- @Envapt('CONFIG_JSON', { converter: 'json', fallback: {} })
322
+ @Envapt('CONFIG_JSON', { converter: Converters.Json, fallback: {} })
207
323
  static readonly config: object;
208
324
 
209
- @Envapt('API_URL', { converter: 'url', fallback: new URL('http://localhost') })
325
+ @Envapt('API_URL', { converter: Converters.Url, fallback: new URL('http://localhost') })
210
326
  static readonly apiUrl: URL;
211
327
 
212
- @Envapt('TIMEOUT', { converter: 'time', fallback: 5000 })
328
+ @Envapt('TIMEOUT', { converter: Converters.Time, fallback: 5000 })
213
329
  static readonly timeout: number; // Converts "30s" to 30000ms
214
330
 
215
331
  // Instance properties work the same way
216
- @Envapt('CACHE_TTL', { converter: 'time', fallback: 3600000 })
332
+ @Envapt('CACHE_TTL', { converter: Converters.Time, fallback: 3600000 })
217
333
  declare readonly cacheTtl: number; // "1h" becomes 3600000ms
218
334
  }
219
335
  ```
220
336
 
337
+ > [!WARNING]
338
+ > These will throw runtime errors due to type mismatches:
339
+ >
340
+ > ```ts
341
+ > // โŒ String converter with number fallback
342
+ > @Envapt('VAR', { converter: Converters.String, fallback: 42 })
343
+ >
344
+ > // โŒ URL converter with string fallback
345
+ > @Envapt('VAR', { converter: Converters.Url, fallback: 'http://example.com' })
346
+ >
347
+ > // โœ… Use primitive constructors for type coercion instead
348
+ > @Envapt('VAR', { converter: String, fallback: 42 })
349
+ > ```
350
+
221
351
  **Available Built-in Converters:**
222
352
 
223
- - `'string'` - String values
224
- - `'number'` - Numeric values (integers and floats)
225
- - `'integer'` - Integer values only
226
- - `'float'` - Float values only
227
- - `'boolean'` - Boolean values (true/false, yes/no, on/off, 1/0)
228
- - `'bigint'` - BigInt values for large integers
229
- - `'symbol'` - Symbol values (creates symbols from string descriptions)
230
- - `'json'` - JSON objects/arrays (safe parsing with fallback)
231
- - `'array'` - Comma-separated string arrays
232
- - `'url'` - URL objects
233
- - `'regexp'` - Regular expressions (supports `/pattern/flags` syntax)
234
- - `'date'` - Date objects (supports ISO strings and timestamps)
235
- - `'time'` - Time values (converts "5s", "30m", "2h" to milliseconds)
353
+ | **Converter** | **Alias** | **Description** |
354
+ | -------------------- | ----------- | -------------------------------------------------------------------- |
355
+ | `Converters.String` | `'string'` | String values |
356
+ | `Converters.Number` | `'number'` | Numeric values (integers and floats) |
357
+ | `Converters.Integer` | `'integer'` | Integer values only |
358
+ | `Converters.Float` | `'float'` | Float values only |
359
+ | `Converters.Boolean` | `'boolean'` | Boolean values (`true`/`false`, `yes`/`no`, `on`/`off`, `1`/`0`) |
360
+ | `Converters.Bigint` | `'bigint'` | BigInt values for large integers |
361
+ | `Converters.Symbol` | `'symbol'` | Symbol values (creates symbols from string descriptions) |
362
+ | `Converters.Json` | `'json'` | JSON objects/arrays (safe parsing with fallback) |
363
+ | `Converters.Array` | `'array'` | Comma-separated string arrays |
364
+ | `Converters.Url` | `'url'` | URL objects |
365
+ | `Converters.Regexp` | `'regexp'` | Regular expressions (supports `/pattern/flags` syntax) |
366
+ | `Converters.Date` | `'date'` | Date objects (supports ISO strings and timestamps) |
367
+ | `Converters.Time` | `'time'` | Time values (e.g. `"5s"`, `"30m"`, `"2h"` converted to milliseconds) |
236
368
 
237
369
  #### Custom Array Converters
238
370
 
239
371
  For more control over array parsing:
240
372
 
373
+ > [!IMPORTANT]
374
+ > Array converters validate that:
375
+ >
376
+ > 1. **Fallback must be an array** (if provided)
377
+ > 2. **All fallback elements have consistent types** (no mixed types like `['string', 42, true]`)
378
+ > 3. **Array converter `type` matches fallback element types** (if `type` is specified)
379
+
241
380
  ```ts
242
381
  class Config extends Envapter {
243
382
  // Basic array (comma-separated strings)
244
- @Envapt('TAGS', { converter: 'array', fallback: [] })
383
+ @Envapt('TAGS', { converter: Converters.Array, fallback: [] })
245
384
  static readonly tags: string[];
246
385
 
247
386
  // Custom delimiter
@@ -249,7 +388,7 @@ class Config extends Envapter {
249
388
  declare readonly allowedMethods: string[];
250
389
 
251
390
  // Custom delimiter with type conversion
252
- @Envapt('RATE_LIMITS', { converter: { delimiter: ',', type: 'number' }, fallback: [100] })
391
+ @Envapt('RATE_LIMITS', { converter: { delimiter: ',', type: Converters.Number }, fallback: [100] })
253
392
  declare readonly rateLimits: number[];
254
393
 
255
394
  @Envapt('FEATURE_FLAGS', { converter: { delimiter: ';', type: 'boolean' }, fallback: [false] })
@@ -257,10 +396,24 @@ class Config extends Envapter {
257
396
  }
258
397
  ```
259
398
 
399
+ > [!WARNING]
400
+ > These will throw runtime validation errors:
401
+ >
402
+ > ```ts
403
+ > // โŒ Mixed types in fallback array
404
+ > @Envapt('MIXED', { converter: Converters.Array, fallback: ['string', 42, true] })
405
+ >
406
+ > // โŒ Array converter type doesn't match fallback elements
407
+ > @Envapt('NUMS', { converter: { delimiter: ',', type: Converters.Number }, fallback: ['not', 'numbers'] })
408
+ >
409
+ > // โŒ Non-array fallback with array converter
410
+ > @Envapt('INVALID', { converter: Converters.Array, fallback: 'not-an-array' })
411
+ > ```
412
+
260
413
  **ArrayConverter Interface:**
261
414
 
262
415
  - `delimiter: string` - The string used to split array elements
263
- - `type?: BuiltInConverter` - Optional type to convert each element to (excludes 'array', 'json', and 'regexp')
416
+ - `type?: BuiltInConverter` - Optional type to convert each element to (excludes `Converters.Array`, `Converters.Json`, and `Converters.Regexp`)
264
417
 
265
418
  #### Custom Converters
266
419
 
@@ -304,7 +457,7 @@ class Config extends Envapter {
304
457
  static readonly optionalFeature: string | undefined;
305
458
 
306
459
  // Returns null if not found (no fallback provided)
307
- @Envapt('MISSING_CONFIG', { converter: 'string' })
460
+ @Envapt('MISSING_CONFIG', { converter: Converters.String })
308
461
  static readonly missingConfig: string | null;
309
462
 
310
463
  // Uses fallback if not found
@@ -319,19 +472,92 @@ class Config extends Envapter {
319
472
 
320
473
  ### Functional API
321
474
 
475
+ For functional-style environment variable on primitive types:
476
+
322
477
  ```ts
323
- import { Envapter } from 'envapt';
478
+ import { Envapter, Converters } from 'envapt';
324
479
 
325
- // Type-specific getters
480
+ // Basic type-specific getters
326
481
  const str = Envapter.get('STRING_VAR', 'default');
327
482
  const num = Envapter.getNumber('NUMBER_VAR', 42);
328
483
  const bool = Envapter.getBoolean('BOOLEAN_VAR', false);
484
+ const bigint = Envapter.getBigInt('BIGINT_VAR', 100n);
485
+ const symbol = Envapter.getSymbol('SYMBOL_VAR', Symbol('default'));
329
486
 
330
- // Instance methods (same API)
487
+ // Advanced converter methods
488
+ const jsonData = Envapter.getUsing('CONFIG_JSON', Converters.Json);
489
+ const urlArray = Envapter.getUsing('API_URLS', { delimiter: ',', type: Converters.Url });
490
+ const customData = Envapter.getWith('RAW_DATA', (raw) => raw?.split('|').map((s) => s.trim()));
491
+
492
+ // Instance methods (same API available)
331
493
  const envapter = new Envapter();
332
494
  const value = envapter.get('VAR', 'default');
495
+ const processed = envapter.getUsing('DATA', Converters.Array);
333
496
  ```
334
497
 
498
+ For functional-style environment variable access with converters:
499
+
500
+ ```ts
501
+ import { Envapter, Converters } from 'envapt';
502
+
503
+ // Use built-in converters directly
504
+ const config = Envapter.getUsing('API_CONFIG', Converters.Json, { default: 'value' });
505
+ const urls = Envapter.getUsing('SERVICE_URLS', { delimiter: '|', type: Converters.Url });
506
+ const typedConfig = Envapter.getUsing<{ host: string; port: number; ssl: boolean }>('DATABASE_CONFIG', Converters.Json);
507
+ // typedConfig is now typed as { host: string; port: number; ssl: boolean } instead of JsonValue | undefined
508
+
509
+ // Use custom converter functions
510
+ const processedData = Envapter.getWith(
511
+ 'RAW_DATA',
512
+ (raw, fallback) => {
513
+ if (!raw) return fallback ?? [];
514
+ return raw.split(',').map((item) => ({ name: item.trim(), enabled: true }));
515
+ },
516
+ []
517
+ );
518
+
519
+ // Instance methods work the same way
520
+ const envapter = new Envapter();
521
+ const result = envapter.getUsing('DATABASE_CONFIG', Converters.Json);
522
+ ```
523
+
524
+ > [!TIP]
525
+ > **Type Override with `getUsing`**
526
+ >
527
+ > You can explicitly specify the return type for `getUsing` when TypeScript's inference isn't specific enough (especially useful with `Converters.Json`):
528
+ >
529
+ > ```ts
530
+ > // Default behavior
531
+ > const config = Envapter.getUsing('CONFIG', Converters.Json); // type: JsonValue | undefined (undefined because no fallback)
532
+ >
533
+ > // Override with specific interface
534
+ > interface DatabaseConfig {
535
+ > host: string;
536
+ > port: number;
537
+ > ssl: boolean;
538
+ > }
539
+ > const dbConfig = Envapter.getUsing<DatabaseConfig>('DB_CONFIG', Converters.Json);
540
+ > // dbConfig is now properly typed as DatabaseConfig
541
+ > ```
542
+ >
543
+ > _Make sure the fallback value matches the expected type, if you use a fallback. Otherwise you'll see a TypeScript error._\
544
+ > _This does NOT validate the type at runtime. You'll need to handle that yourself._
545
+
546
+ ### Converter Type Quick Reference
547
+
548
+ | **Use Case** | **Converter Type** | **Example** |
549
+ | ----------------------- | ------------------------- | --------------------------------------------------------- |
550
+ | **Type coercion** | Primitive constructors | `converter: String` |
551
+ | **Strict validation** | Built-in converters | `converter: Converters.String` |
552
+ | **Array parsing** | Built-in Array converters | `converter: { delimiter: ',', type?: Converters.String }` |
553
+ | **Complex transforms** | Custom function | `converter: (raw, fallback) => ...` |
554
+ | **Functional built-in** | `getUsing()` method | `Envapter.getUsing('VAR', Converters.Json)` |
555
+ | **Type override** | `getUsing<T>()` method | `Envapter.getUsing<MyType>('VAR', Converters.Json)` |
556
+ | **Functional custom** | `getWith()` method | `Envapter.getWith('VAR', (raw) => transform(raw))` |
557
+
558
+ > [!TIP]
559
+ > **Use the `Converters` enum**. They look better. Start with built-in converters, use primitive constructors when you need coercion, and custom converters for complex transforms.
560
+
335
561
  ## Environment Detection
336
562
 
337
563
  Envapt automatically detects your environment from these variables (in order):
@@ -348,7 +574,7 @@ Supported values: `development`, `staging`, `production` (case-sensitive)
348
574
  import { Envapter, EnvaptEnvironment } from 'envapt';
349
575
 
350
576
  // Check current environment
351
- console.log(Envapter.environment); // Environment.Development
577
+ console.log(Envapter.environment); // Environment.Development (default)
352
578
  console.log(Envapter.isProduction); // false
353
579
  console.log(Envapter.isDevelopment); // true
354
580
  console.log(Envapter.isStaging); // false
@@ -358,6 +584,8 @@ Envapter.environment = EnvaptEnvironment.Production;
358
584
  Envapter.environment = 'staging'; // string also works
359
585
  ```
360
586
 
587
+ ## Configuration
588
+
361
589
  ### Multiple .env Files
362
590
 
363
591
  ```ts
@@ -373,6 +601,29 @@ Envapter.envPaths = resolve(__dirname, '.env.production');
373
601
  // Or just don't set a path for it to default to .env at the root of your project
374
602
  ```
375
603
 
604
+ ### Dotenv Configuration
605
+
606
+ Envapt allows you to customize dotenv behavior by setting configuration options:
607
+
608
+ ```ts
609
+ import { Envapter } from 'envapt';
610
+
611
+ // Set dotenv configuration options
612
+ Envapter.dotenvConfig = {
613
+ encoding: 'latin1', // File encoding (default: 'utf8')
614
+ debug: true, // Enable debug logging
615
+ override: true, // Override existing environment variables
616
+ quiet: false, // Suppress non-error output (default: true)
617
+ DOTENV_KEY: 'key...' // Decryption key for .env.vault files
618
+ };
619
+
620
+ // Get current configuration
621
+ console.log(Envapter.dotenvConfig);
622
+ ```
623
+
624
+ > [!NOTE]
625
+ > The `path` and `processEnv` options are managed internally by Envapter and cannot be set via `dotenvConfig`.
626
+
376
627
  ## Template Variables
377
628
 
378
629
  Envapt supports variable interpolation with `${VARIABLE}` syntax:
@@ -396,19 +647,79 @@ CIRCULAR_B=${CIRCULAR_A}
396
647
 
397
648
  Circular references are detected and preserved as-is rather than causing infinite loops.
398
649
 
650
+ ## Error Handling
651
+
652
+ Envapt provides detailed error codes for better debugging and error handling:
653
+
654
+ ```ts
655
+ import { EnvaptError, EnvaptErrorCodes } from 'envapt';
656
+
657
+ try {
658
+ // This will throw an error for invalid configuration
659
+ Envapter.dotenvConfig = { path: '.env.custom' };
660
+ } catch (error) {
661
+ if (error instanceof EnvaptError) {
662
+ console.log('Error code:', error.code);
663
+ console.log('Error message:', error.message);
664
+
665
+ // Handle specific error types
666
+ switch (error.code) {
667
+ case EnvaptErrorCodes.InvalidUserDefinedConfig:
668
+ console.log('Invalid configuration provided');
669
+ break;
670
+ case EnvaptErrorCodes.EnvFileNotFound:
671
+ console.log('Environment file not found');
672
+ break;
673
+ default:
674
+ console.warn('Unhandled error code:', error.code);
675
+ break;
676
+ }
677
+ }
678
+ }
679
+ ```
680
+
681
+ ### Error Code Reference
682
+
683
+ #### ๐Ÿ”ง Fallback Errors (1xx)
684
+
685
+ | **Error Code** | **Description** |
686
+ | ---------------------------------------- | --------------------------------------------------------- |
687
+ | `InvalidFallback` (101) | Invalid fallback value provided |
688
+ | `InvalidFallbackType` (102) | Fallback value type doesn't match expected converter type |
689
+ | `ArrayFallbackElementTypeMismatch` (103) | Array fallback contains elements of wrong type |
690
+ | `FallbackConverterTypeMismatch` (104) | Fallback type doesn't match the specified converter |
691
+
692
+ #### ๐Ÿงช Converter Errors (2xx)
693
+
694
+ | **Error Code** | **Description** |
695
+ | --------------------------------- | ---------------------------------------------- |
696
+ | `InvalidArrayConverterType` (201) | Invalid array converter configuration provided |
697
+ | `InvalidBuiltInConverter` (202) | Invalid built-in converter specified |
698
+ | `InvalidCustomConverter` (203) | Custom converter function is invalid |
699
+ | `InvalidConverterType` (204) | Converter type is not recognized |
700
+ | `PrimitiveCoercionFailed` (205) | Primitive type coercion failed |
701
+
702
+ #### ๐Ÿ“‚ Environment File & Config Errors (3xx)
703
+
704
+ | **Error Code** | **Description** |
705
+ | -------------------------------- | ---------------------------------------------- |
706
+ | `MissingDelimiter` (301) | Delimiter is missing in array converter config |
707
+ | `InvalidUserDefinedConfig` (302) | Invalid user-defined configuration provided |
708
+ | `EnvFilesNotFound` (303) | Specified environment file doesn't exist |
709
+
399
710
  ## Advanced Examples
400
711
 
401
712
  ### Complex Configuration
402
713
 
403
714
  ```ts
404
- import { Envapt, Envapter } from 'envapt';
715
+ import { Envapt, Envapter, Converters } from 'envapt';
405
716
 
406
717
  class AppConfig extends Envapter {
407
718
  // Global settings (static)
408
719
  @Envapt('PORT', 3000)
409
720
  static readonly port: number;
410
721
 
411
- @Envapt('REQUEST_TIMEOUT', { converter: 'time', fallback: 10000 })
722
+ @Envapt('REQUEST_TIMEOUT', { converter: Converters.Time, fallback: 10000 })
412
723
  static readonly requestTimeout: number; // "5s" -> 5000ms (if env is set to "5s")
413
724
 
414
725
  @Envapt('FEATURE_FLAGS', {
@@ -424,7 +735,7 @@ class AppConfig extends Envapter {
424
735
  @Envapt('DB_URL', 'sqlite://memory')
425
736
  declare readonly databaseUrl: string;
426
737
 
427
- @Envapt('CACHE_TTL', { converter: 'time', fallback: 3600000 })
738
+ @Envapt('CACHE_TTL', { converter: Converters.Time, fallback: 3600000 })
428
739
  declare readonly cacheTtl: number; // "1h" -> 3600000ms
429
740
 
430
741
  @Envapt('REDIS_URLS', {
@@ -440,3 +751,20 @@ class AppConfig extends Envapter {
440
751
  }
441
752
  }
442
753
  ```
754
+
755
+ ---
756
+
757
+ <hr/>
758
+
759
+ <p align="center">
760
+ <a href="https://github.com/materwelondhruv/envapt">โญ๏ธ Star it on GitHub</a> โ€ข
761
+ <a href="https://github.com/materwelondhruv/envapt/issues">๐Ÿ› Report a bug</a> โ€ข
762
+ <a href="https://github.com/materwelondhruv/envapt/issues/new?labels=enhancement">๐Ÿ’ก Request a feature</a>
763
+ </p>
764
+
765
+ <p align="center">
766
+ <sub>
767
+ Built by <a href="https://github.com/materwelondhruv">@materwelonDhruv</a> โ€ข Licensed under
768
+ <a href="LICENSE">Apache 2.0</a>
769
+ </sub>
770
+ </p>