envapt 4.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -231
- package/dist/index.cjs +13 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +102 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.mjs +13 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -16
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="assets/banner.png" alt="Envapt – The apt way to handle environment variables" width="100%" />
|
|
2
|
+
<img src="/.github/assets/banner.png" alt="Envapt – The apt way to handle environment variables" width="100%" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
@@ -46,45 +46,45 @@
|
|
|
46
46
|
|
|
47
47
|
- [Requirements](#requirements)
|
|
48
48
|
- [Quick Start](#quick-start)
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
- [Installation](#installation)
|
|
50
|
+
- [Basic Usage](#basic-usage)
|
|
51
51
|
|
|
52
52
|
### 🧬 API Reference
|
|
53
53
|
|
|
54
54
|
- [API Reference](#api-reference)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
- [Decorator API](#decorator-api)
|
|
56
|
+
- [Modern Syntax (Recommended)](#modern-syntax-recommended)
|
|
57
|
+
- [Classic Syntax](#classic-syntax)
|
|
58
|
+
- [Automatic Runtime Type Detection](#automatic-runtime-type-detection)
|
|
59
|
+
- [Primitive Converters](#primitive-converters)
|
|
60
|
+
- [Built-in Converters](#built-in-converters)
|
|
61
|
+
- [Custom Array Converters](#custom-array-converters)
|
|
62
|
+
- [Custom Converters](#custom-converters)
|
|
63
|
+
- [Handling Missing Values](#handling-missing-values)
|
|
64
|
+
- [Functional API](#functional-api)
|
|
65
|
+
- [Tagged Template Resolver](#tagged-template-resolver)
|
|
66
|
+
- [Converter Type Quick Reference](#converter-type-quick-reference)
|
|
67
67
|
|
|
68
68
|
### 🌍 Environment & Templates
|
|
69
69
|
|
|
70
70
|
- [Environment Detection](#environment-detection)
|
|
71
|
-
|
|
71
|
+
- [Environment Management](#environment-management)
|
|
72
72
|
- [Template Variables](#template-variables)
|
|
73
|
-
|
|
73
|
+
- [Circular Reference Protection](#circular-reference-protection)
|
|
74
74
|
|
|
75
75
|
### 🛠 Configuration & Errors
|
|
76
76
|
|
|
77
77
|
- [Configuration](#configuration)
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
- [Multiple .env Files](#multiple-env-files)
|
|
79
|
+
- [Dotenv Configuration](#dotenv-configuration)
|
|
80
80
|
- [Error Handling](#error-handling)
|
|
81
|
-
|
|
81
|
+
- [Error Code Reference](#error-code-reference)
|
|
82
82
|
|
|
83
83
|
### 🚀 Examples
|
|
84
84
|
|
|
85
85
|
- [Advanced Examples](#advanced-examples)
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
- [JavaScript](#javascript)
|
|
87
|
+
- [TypeScript](#typescript)
|
|
88
88
|
|
|
89
89
|
<div align="right">
|
|
90
90
|
|
|
@@ -103,11 +103,11 @@
|
|
|
103
103
|
```jsonc
|
|
104
104
|
// tsconfig.json (required settings for decorators)
|
|
105
105
|
{
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
"experimentalDecorators": true,
|
|
107
|
+
"module": "esnext", // or "nodenext"
|
|
108
|
+
"moduleResolution": "bundler", // or "nodenext"
|
|
109
|
+
"target": "ESNext",
|
|
110
|
+
"lib": ["ESNext"]
|
|
111
111
|
}
|
|
112
112
|
```
|
|
113
113
|
|
|
@@ -175,36 +175,36 @@ import { Envapt, Envapter, Converters } from 'envapt';
|
|
|
175
175
|
|
|
176
176
|
// Global app configuration (static properties)
|
|
177
177
|
class AppConfig extends Envapter {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
178
|
+
@Envapt('APP_PORT', 3000)
|
|
179
|
+
static readonly port: number;
|
|
180
|
+
|
|
181
|
+
// The Classic Syntax only works for Primitive Converters. Converters.Url is a Built-in Converter.
|
|
182
|
+
@Envapt('APP_URL', { fallback: new URL('http://localhost:3000'), converter: Converters.Url })
|
|
183
|
+
static readonly url: URL;
|
|
184
|
+
|
|
185
|
+
@Envapt('ALLOWED_ORIGINS', {
|
|
186
|
+
fallback: ['http://localhost:3000'],
|
|
187
|
+
converter: Converters.Array
|
|
188
|
+
})
|
|
189
|
+
static readonly allowedOrigins: string[];
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// Service configuration (instance properties)
|
|
193
193
|
class DatabaseService {
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
@Envapt('DATABASE_URL', 'sqlite://memory')
|
|
195
|
+
declare readonly databaseUrl: string;
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
// Will detect that '10' is a number and set the runtime type accordingly
|
|
198
|
+
@Envapt('MAX_CONNECTIONS', 10)
|
|
199
|
+
declare readonly maxConnections: number;
|
|
200
200
|
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
@Envapt('REQUEST_TIMEOUT', { converter: Converters.Time, fallback: 5000 })
|
|
202
|
+
declare readonly timeout: number; // Converts "5s" to 5000ms
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
204
|
+
async connect() {
|
|
205
|
+
console.log(`Connecting to ${this.databaseUrl}`);
|
|
206
|
+
// Connection logic here
|
|
207
|
+
}
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// Usage
|
|
@@ -267,29 +267,29 @@ Types are automatically inferred from fallback values.
|
|
|
267
267
|
|
|
268
268
|
```ts
|
|
269
269
|
class Config extends Envapter {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
270
|
+
// Static properties for global settings
|
|
271
|
+
@Envapt('APP_NAME', 'MyApp') // string
|
|
272
|
+
static readonly appName: string;
|
|
273
273
|
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
@Envapt('APP_PORT', 3000) // number
|
|
275
|
+
static readonly port: number;
|
|
276
276
|
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
@Envapt('DEBUG_MODE', false) // boolean
|
|
278
|
+
static readonly debugMode: boolean;
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
280
|
+
// Instance properties for service-specific settings
|
|
281
|
+
@Envapt('SMTP_HOST', 'localhost') // string
|
|
282
|
+
declare readonly smtpHost: string;
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
@Envapt('SMTP_PORT', 587) // number
|
|
285
|
+
declare readonly smtpPort: number;
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
@Envapt('SMTP_SECURE', true) // boolean
|
|
288
|
+
declare readonly smtpSecure: boolean;
|
|
289
289
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
sendEmail(to: string, subject: string) {
|
|
291
|
+
console.log(`Sending via ${this.smtpHost}:${this.smtpPort}`);
|
|
292
|
+
}
|
|
293
293
|
}
|
|
294
294
|
```
|
|
295
295
|
|
|
@@ -304,28 +304,28 @@ Envapt allows using the 5 "primitive" type-like converters. These **will** coerc
|
|
|
304
304
|
|
|
305
305
|
```ts
|
|
306
306
|
class Config extends Envapter {
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
@Envapt('PORT_STRING', { fallback: 'hello-world', converter: String })
|
|
308
|
+
static readonly portAsString: string;
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
@Envapt('DEBUG_FLAG', { fallback: true, converter: Boolean })
|
|
311
|
+
static readonly debugMode: boolean;
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
@Envapt('USER_ID', { fallback: 12345, converter: Number })
|
|
314
|
+
static readonly userId: number;
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
@Envapt('MAX_SAFE_INT', { fallback: 9007199254740991n, converter: BigInt })
|
|
317
|
+
static readonly maxSafeInt: bigint;
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
@Envapt('APP_INSTANCE', { fallback: Symbol(main), converter: Symbol })
|
|
320
|
+
static readonly appInstance: symbol;
|
|
321
321
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
322
|
+
// Instance properties work the same way
|
|
323
|
+
@Envapt('CONNECTION_TIMEOUT', { fallback: 5000, converter: Number })
|
|
324
|
+
declare readonly timeout: number;
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
// Type coercion example
|
|
327
|
+
@Envapt('PERMISSIONS', { fallback: '72394823472342983', converter: BigInt })
|
|
328
|
+
declare readonly permissions: bigint; // Converts "72394823472342983" to BigInt
|
|
329
329
|
}
|
|
330
330
|
```
|
|
331
331
|
|
|
@@ -354,32 +354,32 @@ Envapt provides many built-in converters for common patterns:
|
|
|
354
354
|
|
|
355
355
|
```ts
|
|
356
356
|
class Config extends Envapter {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
357
|
+
// Basic types
|
|
358
|
+
@Envapt('APP_NAME', { converter: Converters.String, fallback: 'MyApp' })
|
|
359
|
+
static readonly appName: string;
|
|
360
360
|
|
|
361
|
-
|
|
362
|
-
|
|
361
|
+
@Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
|
|
362
|
+
static readonly port: number;
|
|
363
363
|
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
@Envapt('PRODUCTION_MODE', { converter: Converters.Boolean, fallback: false })
|
|
365
|
+
static readonly productionMode: boolean;
|
|
366
366
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
367
|
+
// Advanced types
|
|
368
|
+
@Envapt('CORS_ORIGINS', { converter: Converters.Array, fallback: [] })
|
|
369
|
+
static readonly corsOrigins: string[];
|
|
370
370
|
|
|
371
|
-
|
|
372
|
-
|
|
371
|
+
@Envapt('CONFIG_JSON', { converter: Converters.Json, fallback: {} })
|
|
372
|
+
static readonly config: object;
|
|
373
373
|
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
@Envapt('API_URL', { converter: Converters.Url, fallback: new URL('http://localhost') })
|
|
375
|
+
static readonly apiUrl: URL;
|
|
376
376
|
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
@Envapt('TIMEOUT', { converter: Converters.Time, fallback: 5000 })
|
|
378
|
+
static readonly timeout: number; // Converts "30s" to 30000ms
|
|
379
379
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
380
|
+
// Instance properties work the same way
|
|
381
|
+
@Envapt('CACHE_TTL', { converter: Converters.Time, fallback: 3600000 })
|
|
382
|
+
declare readonly cacheTtl: number; // "1h" becomes 3600000ms
|
|
383
383
|
}
|
|
384
384
|
```
|
|
385
385
|
|
|
@@ -428,20 +428,20 @@ For more control over array parsing:
|
|
|
428
428
|
|
|
429
429
|
```ts
|
|
430
430
|
class Config extends Envapter {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
431
|
+
// Basic array (comma-separated strings)
|
|
432
|
+
@Envapt('TAGS', { converter: Converters.Array, fallback: [] })
|
|
433
|
+
static readonly tags: string[];
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
435
|
+
// Custom delimiter
|
|
436
|
+
@Envapt('ALLOWED_METHODS', { converter: { delimiter: '|' }, fallback: ['GET'] })
|
|
437
|
+
declare readonly allowedMethods: string[];
|
|
438
438
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
439
|
+
// Custom delimiter with type conversion
|
|
440
|
+
@Envapt('RATE_LIMITS', { converter: { delimiter: ',', type: Converters.Number }, fallback: [100] })
|
|
441
|
+
declare readonly rateLimits: number[];
|
|
442
442
|
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
@Envapt('FEATURE_FLAGS', { converter: { delimiter: ';', type: 'boolean' }, fallback: [false] })
|
|
444
|
+
declare readonly featureFlags: boolean[];
|
|
445
445
|
}
|
|
446
446
|
```
|
|
447
447
|
|
|
@@ -470,28 +470,28 @@ Transform environment values to any type:
|
|
|
470
470
|
|
|
471
471
|
```ts
|
|
472
472
|
class Config extends Envapter {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
473
|
+
@Envapt('TAGS', {
|
|
474
|
+
fallback: new Set(['default']),
|
|
475
|
+
converter: (raw, fallback) => {
|
|
476
|
+
if (!raw) return fallback;
|
|
477
|
+
return new Set(raw.split(',').map((s) => s.trim()));
|
|
478
|
+
}
|
|
479
|
+
})
|
|
480
|
+
static readonly tags: Set<string>;
|
|
481
|
+
|
|
482
|
+
@Envapt('NOTIFICATION_CHANNELS', {
|
|
483
|
+
fallback: new Map([['email', 'enabled']]),
|
|
484
|
+
converter: (raw, fallback) => {
|
|
485
|
+
if (!raw) return fallback;
|
|
486
|
+
const map = new Map();
|
|
487
|
+
raw.split(',').forEach((pair) => {
|
|
488
|
+
const [key, value] = pair.split(':');
|
|
489
|
+
map.set(key?.trim(), value?.trim() || 'enabled');
|
|
490
|
+
});
|
|
491
|
+
return map;
|
|
492
|
+
}
|
|
493
|
+
})
|
|
494
|
+
declare readonly channels: Map<string, string>;
|
|
495
495
|
}
|
|
496
496
|
```
|
|
497
497
|
|
|
@@ -520,21 +520,21 @@ Control what happens when environment variables don't exist:
|
|
|
520
520
|
|
|
521
521
|
```ts
|
|
522
522
|
class Config extends Envapter {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
523
|
+
// Returns undefined if not found
|
|
524
|
+
@Envapt('OPTIONAL_FEATURE', { fallback: undefined })
|
|
525
|
+
static readonly optionalFeature: string | undefined;
|
|
526
526
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
527
|
+
// Returns null if not found (no fallback provided)
|
|
528
|
+
@Envapt('MISSING_CONFIG', { converter: Converters.String })
|
|
529
|
+
static readonly missingConfig: string | null;
|
|
530
530
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
531
|
+
// Uses fallback if not found
|
|
532
|
+
@Envapt('DEFAULT_THEME', { fallback: 'light' })
|
|
533
|
+
static readonly defaultTheme: string;
|
|
534
534
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
535
|
+
// Instance properties work the same way
|
|
536
|
+
@Envapt('LOG_FILE_PATH', { fallback: undefined })
|
|
537
|
+
declare readonly logFilePath: string | undefined;
|
|
538
538
|
}
|
|
539
539
|
```
|
|
540
540
|
|
|
@@ -602,9 +602,9 @@ const result = envapter.getUsing('DATABASE_CONFIG', Converters.Json);
|
|
|
602
602
|
>
|
|
603
603
|
> // Override with specific interface
|
|
604
604
|
> interface DatabaseConfig {
|
|
605
|
-
>
|
|
606
|
-
>
|
|
607
|
-
>
|
|
605
|
+
> host: string;
|
|
606
|
+
> port: number;
|
|
607
|
+
> ssl: boolean;
|
|
608
608
|
> }
|
|
609
609
|
> const dbConfig = Envapter.getUsing<DatabaseConfig>('DB_CONFIG', Converters.Json);
|
|
610
610
|
> // dbConfig is now properly typed as DatabaseConfig
|
|
@@ -738,11 +738,11 @@ import { Envapter } from 'envapt';
|
|
|
738
738
|
|
|
739
739
|
// Set dotenv configuration options
|
|
740
740
|
Envapter.dotenvConfig = {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
741
|
+
encoding: 'latin1', // File encoding (default: 'utf8')
|
|
742
|
+
debug: true, // Enable debug logging
|
|
743
|
+
override: true, // Override existing environment variables
|
|
744
|
+
quiet: false, // Suppress non-error output (default: true)
|
|
745
|
+
DOTENV_KEY: 'key...' // Decryption key for .env.vault files
|
|
746
746
|
};
|
|
747
747
|
|
|
748
748
|
// Get current configuration
|
|
@@ -795,26 +795,26 @@ Envapt provides detailed error codes for better debugging and error handling:
|
|
|
795
795
|
import { EnvaptError, EnvaptErrorCodes } from 'envapt';
|
|
796
796
|
|
|
797
797
|
try {
|
|
798
|
-
|
|
799
|
-
|
|
798
|
+
// This will throw an error for invalid configuration
|
|
799
|
+
Envapter.dotenvConfig = { path: '.env.custom' };
|
|
800
800
|
} catch (error) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
801
|
+
if (error instanceof EnvaptError) {
|
|
802
|
+
console.log('Error code:', error.code);
|
|
803
|
+
console.log('Error message:', error.message);
|
|
804
|
+
|
|
805
|
+
// Handle specific error types
|
|
806
|
+
switch (error.code) {
|
|
807
|
+
case EnvaptErrorCodes.InvalidUserDefinedConfig:
|
|
808
|
+
console.log('Invalid configuration provided');
|
|
809
|
+
break;
|
|
810
|
+
case EnvaptErrorCodes.EnvFileNotFound:
|
|
811
|
+
console.log('Environment file not found');
|
|
812
|
+
break;
|
|
813
|
+
default:
|
|
814
|
+
console.warn('Unhandled error code:', error.code);
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
816
817
|
}
|
|
817
|
-
}
|
|
818
818
|
}
|
|
819
819
|
```
|
|
820
820
|
|
|
@@ -862,35 +862,35 @@ import { Envapter, Converters } from 'envapt';
|
|
|
862
862
|
|
|
863
863
|
// Global configuration
|
|
864
864
|
const config = {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
865
|
+
port: Envapter.getNumber('PORT', 3000),
|
|
866
|
+
requestTimeout: Envapter.getUsing('REQUEST_TIMEOUT', Converters.Time, 10000), // "5s" -> 5000ms
|
|
867
|
+
featureFlags: Envapter.getWith(
|
|
868
|
+
'FEATURE_FLAGS',
|
|
869
|
+
(raw, fallback) => {
|
|
870
|
+
if (!raw) return fallback;
|
|
871
|
+
return new Set(raw.split(',').map((s) => s.trim()));
|
|
872
|
+
},
|
|
873
|
+
new Set(['basic'])
|
|
874
|
+
)
|
|
875
875
|
};
|
|
876
876
|
|
|
877
877
|
// Service configuration
|
|
878
878
|
class DatabaseService {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
879
|
+
constructor() {
|
|
880
|
+
this.databaseUrl = Envapter.get('DB_URL', 'sqlite://memory');
|
|
881
|
+
this.cacheTtl = Envapter.getUsing('CACHE_TTL', Converters.Time, 3600000); // "1h" -> 3600000ms
|
|
882
|
+
this.redisUrls = Envapter.getWith(
|
|
883
|
+
'REDIS_URLS',
|
|
884
|
+
(raw, fallback) => (raw ? raw.split(',').map((s) => new URL(s)) : fallback),
|
|
885
|
+
[new URL('redis://localhost:6379')]
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
async initialize() {
|
|
890
|
+
console.log(`App running on port ${config.port}`);
|
|
891
|
+
console.log(`Database: ${this.databaseUrl}`);
|
|
892
|
+
console.log(`Cache TTL: ${this.cacheTtl}ms`);
|
|
893
|
+
}
|
|
894
894
|
}
|
|
895
895
|
```
|
|
896
896
|
|
|
@@ -900,40 +900,40 @@ class DatabaseService {
|
|
|
900
900
|
import { Envapt, Envapter, Converters } from 'envapt';
|
|
901
901
|
|
|
902
902
|
class AppConfig extends Envapter {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
903
|
+
// Global settings (static)
|
|
904
|
+
@Envapt('PORT', 3000)
|
|
905
|
+
static readonly port: number;
|
|
906
|
+
|
|
907
|
+
@Envapt('REQUEST_TIMEOUT', { converter: Converters.Time, fallback: 10000 })
|
|
908
|
+
static readonly requestTimeout: number; // "5s" -> 5000ms (if env is set to "5s")
|
|
909
|
+
|
|
910
|
+
@Envapt('FEATURE_FLAGS', {
|
|
911
|
+
fallback: new Set(['basic']),
|
|
912
|
+
converter: (raw, fallback) => {
|
|
913
|
+
if (!raw) return fallback;
|
|
914
|
+
return new Set(raw.split(',').map((s) => s.trim()));
|
|
915
|
+
}
|
|
916
|
+
})
|
|
917
|
+
static readonly featureFlags: Set<string>;
|
|
918
|
+
|
|
919
|
+
// Service settings (instance)
|
|
920
|
+
@Envapt('DB_URL', 'sqlite://memory')
|
|
921
|
+
declare readonly databaseUrl: string;
|
|
922
|
+
|
|
923
|
+
@Envapt('CACHE_TTL', { converter: Converters.Time, fallback: 3600000 })
|
|
924
|
+
declare readonly cacheTtl: number; // "1h" -> 3600000ms
|
|
925
|
+
|
|
926
|
+
@Envapt('REDIS_URLS', {
|
|
927
|
+
fallback: [new URL('redis://localhost:6379')],
|
|
928
|
+
converter: (raw, fallback) => (raw ? raw.split(',').map((s) => new URL(s)) : fallback)
|
|
929
|
+
})
|
|
930
|
+
declare readonly redisUrls: URL[];
|
|
931
|
+
|
|
932
|
+
async initialize() {
|
|
933
|
+
console.log(`App running on port ${AppConfig.port}`);
|
|
934
|
+
console.log(`Database: ${this.databaseUrl}`);
|
|
935
|
+
console.log(`Cache TTL: ${this.cacheTtl}ms`);
|
|
915
936
|
}
|
|
916
|
-
})
|
|
917
|
-
static readonly featureFlags: Set<string>;
|
|
918
|
-
|
|
919
|
-
// Service settings (instance)
|
|
920
|
-
@Envapt('DB_URL', 'sqlite://memory')
|
|
921
|
-
declare readonly databaseUrl: string;
|
|
922
|
-
|
|
923
|
-
@Envapt('CACHE_TTL', { converter: Converters.Time, fallback: 3600000 })
|
|
924
|
-
declare readonly cacheTtl: number; // "1h" -> 3600000ms
|
|
925
|
-
|
|
926
|
-
@Envapt('REDIS_URLS', {
|
|
927
|
-
fallback: [new URL('redis://localhost:6379')],
|
|
928
|
-
converter: (raw, fallback) => (raw ? raw.split(',').map((s) => new URL(s)) : fallback)
|
|
929
|
-
})
|
|
930
|
-
declare readonly redisUrls: URL[];
|
|
931
|
-
|
|
932
|
-
async initialize() {
|
|
933
|
-
console.log(`App running on port ${AppConfig.port}`);
|
|
934
|
-
console.log(`Database: ${this.databaseUrl}`);
|
|
935
|
-
console.log(`Cache TTL: ${this.cacheTtl}ms`);
|
|
936
|
-
}
|
|
937
937
|
}
|
|
938
938
|
```
|
|
939
939
|
|
package/dist/index.cjs
CHANGED
|
@@ -228,7 +228,10 @@ var Validator = class {
|
|
|
228
228
|
`Failed to coerce fallback value using ${converter.name}: ${error.message}`
|
|
229
229
|
);
|
|
230
230
|
}
|
|
231
|
-
throw new EnvaptError(
|
|
231
|
+
throw new EnvaptError(
|
|
232
|
+
205 /* PrimitiveCoercionFailed */,
|
|
233
|
+
`Unknown primitive converter: ${converter.name}`
|
|
234
|
+
);
|
|
232
235
|
}
|
|
233
236
|
/**
|
|
234
237
|
* Make sure the user hasn't provided prohibited options in their dotenv config
|
|
@@ -338,8 +341,8 @@ var BuiltInConverters = class _BuiltInConverters {
|
|
|
338
341
|
static {
|
|
339
342
|
__name(this, "BuiltInConverters");
|
|
340
343
|
}
|
|
341
|
-
static string(raw,
|
|
342
|
-
return String(raw)
|
|
344
|
+
static string(raw, _fallback) {
|
|
345
|
+
return String(raw);
|
|
343
346
|
}
|
|
344
347
|
static number(raw, fallback) {
|
|
345
348
|
const parsed = Number(raw);
|
|
@@ -682,9 +685,12 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
682
685
|
const parsed = this.parser.resolveTemplate(key, String(rawVal));
|
|
683
686
|
let result;
|
|
684
687
|
if (type === 1 /* Number */) result = BuiltInConverters.number(parsed, def);
|
|
685
|
-
else if (type === 2 /* Boolean */)
|
|
686
|
-
|
|
687
|
-
else if (type ===
|
|
688
|
+
else if (type === 2 /* Boolean */)
|
|
689
|
+
result = BuiltInConverters.boolean(parsed, def);
|
|
690
|
+
else if (type === 3 /* BigInt */)
|
|
691
|
+
result = BuiltInConverters.bigint(parsed, def);
|
|
692
|
+
else if (type === 4 /* Symbol */)
|
|
693
|
+
result = BuiltInConverters.symbol(parsed, def);
|
|
688
694
|
else result = BuiltInConverters.string(parsed, def);
|
|
689
695
|
return result;
|
|
690
696
|
}
|
|
@@ -885,6 +891,7 @@ var Converters = /* @__PURE__ */ ((Converters2) => {
|
|
|
885
891
|
Converters2["Time"] = "time";
|
|
886
892
|
return Converters2;
|
|
887
893
|
})(Converters || {});
|
|
894
|
+
/* v8 ignore next -- @preserve */
|
|
888
895
|
|
|
889
896
|
exports.Converters = Converters;
|
|
890
897
|
exports.Envapt = Envapt;
|