envapt 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/index.cjs +38 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -39
- package/dist/index.d.ts +63 -39
- package/dist/index.mjs +38 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
- 🔖 **Tagged Template Resolver** - Tagged template literals with environment variable resolution
|
|
35
35
|
- 🌍 **Environment Detection** - Built-in development/staging/production handling
|
|
36
36
|
- 💪 **Edge Case Handling** - Robust validation and parsing for all scenarios
|
|
37
|
+
- 🔑 **Multi-Key Lookups** - Provide ordered lists of env keys and Envapt will use the first value it finds
|
|
37
38
|
- 🛡️ **Type Safety** - Full TypeScript support with proper type inference _(TypeScript optional)_
|
|
38
39
|
- 📂 **Multiple .env Files** - Load from multiple sources
|
|
39
40
|
- ⚡ **Lightweight** - Minimal overhead with [`dotenv`](https://www.npmjs.com/package/dotenv) bundled
|
|
@@ -163,6 +164,10 @@ console.log(`URL: ${url}`); // "http://localhost:8443"
|
|
|
163
164
|
const corsOrigins = Envapter.getUsing('ALLOWED_ORIGINS', Converters.Array, []);
|
|
164
165
|
const dbConfig = Envapter.getUsing('DATABASE_CONFIG', Converters.Json, {});
|
|
165
166
|
|
|
167
|
+
// Multi-key lookup: try primary, then replica, then fall back
|
|
168
|
+
const dbUrl = Envapter.get(['PRIMARY_DB_URL', 'REPLICA_DB_URL'], 'sqlite://memory');
|
|
169
|
+
const httpPort = Envapter.getNumber(['APP_PORT', 'PORT'], 3000);
|
|
170
|
+
|
|
166
171
|
// Tagged template literals
|
|
167
172
|
const message = Envapter.resolve`Server ${'APP_URL'} is ready!`;
|
|
168
173
|
console.log(message); // "Server http://localhost:8443 is ready!"
|
|
@@ -182,6 +187,10 @@ class AppConfig extends Envapter {
|
|
|
182
187
|
@Envapt('APP_URL', { fallback: new URL('http://localhost:3000'), converter: Converters.Url })
|
|
183
188
|
static readonly url: URL;
|
|
184
189
|
|
|
190
|
+
// Prefer CLOUD_REDIS_URL but fall back to classic REDIS_URL when missing
|
|
191
|
+
@Envapt(['CLOUD_REDIS_URL', 'REDIS_URL'], 'redis://localhost:6379')
|
|
192
|
+
static readonly redisUrl: string;
|
|
193
|
+
|
|
185
194
|
@Envapt('ALLOWED_ORIGINS', {
|
|
186
195
|
fallback: ['http://localhost:3000'],
|
|
187
196
|
converter: Converters.Array
|
|
@@ -241,6 +250,11 @@ The `@Envapt` decorator can be used on both **static** and **instance** class pr
|
|
|
241
250
|
@Envapt('ENV_VAR', { fallback?: T, converter?: EnvConverter<T> })
|
|
242
251
|
```
|
|
243
252
|
|
|
253
|
+
> [!NOTE]
|
|
254
|
+
> The first argument can be a string **or** an ordered array of strings:
|
|
255
|
+
> `@Envapt(['PRIMARY_URL', 'SECONDARY_URL'], { fallback: 'https://example.com' })`.
|
|
256
|
+
> Envapt will resolve the first key that exists.
|
|
257
|
+
>
|
|
244
258
|
> [!TIP]
|
|
245
259
|
> **Generic Typing for Better IntelliSense**
|
|
246
260
|
>
|
|
@@ -261,6 +275,13 @@ The `@Envapt` decorator can be used on both **static** and **instance** class pr
|
|
|
261
275
|
@Envapt('ENV_VAR', fallback?, converter?)
|
|
262
276
|
```
|
|
263
277
|
|
|
278
|
+
Need to chain multiple keys with the classic API? Pass an array instead of a string:
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
@Envapt(['HOST_PRIMARY', 'HOST_SECONDARY'], 'localhost')
|
|
282
|
+
static readonly host: string;
|
|
283
|
+
```
|
|
284
|
+
|
|
264
285
|
#### Automatic Runtime Type Detection
|
|
265
286
|
|
|
266
287
|
Types are automatically inferred from fallback values.
|
|
@@ -557,6 +578,9 @@ const jsonData = Envapter.getUsing('CONFIG_JSON', Converters.Json);
|
|
|
557
578
|
const urlArray = Envapter.getUsing('API_URLS', { delimiter: ',', type: Converters.Url });
|
|
558
579
|
const customData = Envapter.getWith('RAW_DATA', (raw) => raw?.split('|').map((s) => s.trim()));
|
|
559
580
|
|
|
581
|
+
// Multi-key inputs work everywhere: Envapt will read left-to-right
|
|
582
|
+
const secretsHost = Envapter.get(['SECRETS_HOST', 'DEFAULT_HOST'], 'localhost');
|
|
583
|
+
|
|
560
584
|
// Instance methods (same API available)
|
|
561
585
|
const envapter = new Envapter();
|
|
562
586
|
const value = envapter.get('VAR', 'default');
|
|
@@ -571,6 +595,7 @@ import { Envapter, Converters } from 'envapt';
|
|
|
571
595
|
// Use built-in converters directly
|
|
572
596
|
const config = Envapter.getUsing('API_CONFIG', Converters.Json, { default: 'value' });
|
|
573
597
|
const urls = Envapter.getUsing('SERVICE_URLS', { delimiter: '|', type: Converters.Url });
|
|
598
|
+
const pgUrl = Envapter.getUsing(['PRIMARY_PG_URL', 'SECONDARY_PG_URL'], Converters.Url);
|
|
574
599
|
|
|
575
600
|
// TypeScript: Use type override for better type inference
|
|
576
601
|
const typedConfig = Envapter.getUsing<{ host: string; port: number; ssl: boolean }>('DATABASE_CONFIG', Converters.Json);
|
|
@@ -846,6 +871,7 @@ try {
|
|
|
846
871
|
| `MissingDelimiter` (301) | Delimiter is missing in array converter config |
|
|
847
872
|
| `InvalidUserDefinedConfig` (302) | Invalid user-defined configuration provided |
|
|
848
873
|
| `EnvFilesNotFound` (303) | Specified environment file doesn't exist |
|
|
874
|
+
| `InvalidKeyInput` (304) | Invalid key input (not string or string array) |
|
|
849
875
|
|
|
850
876
|
<div align="right">
|
|
851
877
|
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ var EnvaptErrorCodes = /* @__PURE__ */ ((EnvaptErrorCodes2) => {
|
|
|
26
26
|
EnvaptErrorCodes2[EnvaptErrorCodes2["MissingDelimiter"] = 301] = "MissingDelimiter";
|
|
27
27
|
EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidUserDefinedConfig"] = 302] = "InvalidUserDefinedConfig";
|
|
28
28
|
EnvaptErrorCodes2[EnvaptErrorCodes2["EnvFilesNotFound"] = 303] = "EnvFilesNotFound";
|
|
29
|
+
EnvaptErrorCodes2[EnvaptErrorCodes2["InvalidKeyInput"] = 304] = "InvalidKeyInput";
|
|
29
30
|
return EnvaptErrorCodes2;
|
|
30
31
|
})(EnvaptErrorCodes || {});
|
|
31
32
|
var EnvaptError = class extends Error {
|
|
@@ -317,6 +318,26 @@ var EnvapterBase = class _EnvapterBase {
|
|
|
317
318
|
EnvaptCache.clear();
|
|
318
319
|
void this.config;
|
|
319
320
|
}
|
|
321
|
+
static resolveKeyInput(keyInput) {
|
|
322
|
+
const keys = Array.isArray(keyInput) ? keyInput : [keyInput];
|
|
323
|
+
const normalizedKeys = keys;
|
|
324
|
+
if (normalizedKeys.length === 0) {
|
|
325
|
+
throw new EnvaptError(304 /* InvalidKeyInput */, "At least one environment key must be provided.");
|
|
326
|
+
}
|
|
327
|
+
if (normalizedKeys.some((k) => typeof k !== "string")) {
|
|
328
|
+
throw new EnvaptError(304 /* InvalidKeyInput */, "Environment keys must be strings.");
|
|
329
|
+
}
|
|
330
|
+
if (normalizedKeys.some((k) => k.trim() === "")) {
|
|
331
|
+
throw new EnvaptError(304 /* InvalidKeyInput */, "Environment keys cannot be empty strings.");
|
|
332
|
+
}
|
|
333
|
+
for (const candidate of normalizedKeys) {
|
|
334
|
+
const value = this.config.get(candidate);
|
|
335
|
+
if (value !== void 0) {
|
|
336
|
+
return { key: candidate, value };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return { key: normalizedKeys[0], value: void 0 };
|
|
340
|
+
}
|
|
320
341
|
static get config() {
|
|
321
342
|
if (EnvaptCache.size === 0) {
|
|
322
343
|
const isolatedEnv = { ...process__default.default.env };
|
|
@@ -332,7 +353,7 @@ var EnvapterBase = class _EnvapterBase {
|
|
|
332
353
|
* Get raw environment variable value without parsing or conversion.
|
|
333
354
|
*/
|
|
334
355
|
getRaw(key) {
|
|
335
|
-
return _EnvapterBase.
|
|
356
|
+
return _EnvapterBase.resolveKeyInput(key).value;
|
|
336
357
|
}
|
|
337
358
|
};
|
|
338
359
|
|
|
@@ -680,9 +701,10 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
680
701
|
}
|
|
681
702
|
static parser = new Parser(new _PrimitiveMethods());
|
|
682
703
|
static _get(key, type, def) {
|
|
683
|
-
const
|
|
704
|
+
const { key: resolvedKey, value } = this.resolveKeyInput(key);
|
|
705
|
+
const rawVal = value;
|
|
684
706
|
if (!rawVal) return def;
|
|
685
|
-
const parsed = this.parser.resolveTemplate(
|
|
707
|
+
const parsed = this.parser.resolveTemplate(resolvedKey, String(rawVal));
|
|
686
708
|
let result;
|
|
687
709
|
if (type === 1 /* Number */) result = BuiltInConverters.number(parsed, def);
|
|
688
710
|
else if (type === 2 /* Boolean */)
|
|
@@ -696,20 +718,19 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
696
718
|
}
|
|
697
719
|
/**
|
|
698
720
|
* Get a string environment variable with optional fallback.
|
|
699
|
-
* Supports template variable resolution using
|
|
721
|
+
* Supports template variable resolution using `${VAR}` syntax.
|
|
722
|
+
* Accepts a single key or an ordered array of keys (first match wins).
|
|
700
723
|
*/
|
|
701
724
|
static get(key, def) {
|
|
702
725
|
return this._get(key, 0 /* String */, def);
|
|
703
726
|
}
|
|
704
|
-
/**
|
|
705
|
-
* @see {@link PrimitiveMethods.get}
|
|
706
|
-
*/
|
|
707
727
|
get(key, def) {
|
|
708
728
|
return _PrimitiveMethods._get(key, 0 /* String */, def);
|
|
709
729
|
}
|
|
710
730
|
/**
|
|
711
731
|
* Get a number environment variable with optional fallback.
|
|
712
732
|
* Automatically converts string values to numbers.
|
|
733
|
+
* Accepts a single key or an ordered array of keys (first match wins).
|
|
713
734
|
*/
|
|
714
735
|
static getNumber(key, def) {
|
|
715
736
|
return this._get(key, 1 /* Number */, def);
|
|
@@ -723,6 +744,7 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
723
744
|
/**
|
|
724
745
|
* Get a boolean environment variable with optional fallback.
|
|
725
746
|
* Recognizes: `1`, `yes`, `true`, 'on' as **true**; `0`, `no`, `false`, 'off' as **false** (case-insensitive).
|
|
747
|
+
* Accepts a single key or an ordered array of keys (first match wins).
|
|
726
748
|
*/
|
|
727
749
|
static getBoolean(key, def) {
|
|
728
750
|
return this._get(key, 2 /* Boolean */, def);
|
|
@@ -736,6 +758,7 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
736
758
|
/**
|
|
737
759
|
* Get a bigint environment variable with optional fallback.
|
|
738
760
|
* Automatically converts string values to bigint.
|
|
761
|
+
* Accepts a single key or an ordered array of keys (first match wins).
|
|
739
762
|
*/
|
|
740
763
|
static getBigInt(key, def) {
|
|
741
764
|
return this._get(key, 3 /* BigInt */, def);
|
|
@@ -749,6 +772,7 @@ var PrimitiveMethods = class _PrimitiveMethods extends EnvironmentMethods {
|
|
|
749
772
|
/**
|
|
750
773
|
* Get a symbol environment variable with optional fallback.
|
|
751
774
|
* Creates a symbol from the string value.
|
|
775
|
+
* Accepts a single key or an ordered array of keys (first match wins).
|
|
752
776
|
*/
|
|
753
777
|
static getSymbol(key, def) {
|
|
754
778
|
return this._get(key, 4 /* Symbol */, def);
|
|
@@ -767,10 +791,10 @@ var AdvancedMethods = class _AdvancedMethods extends PrimitiveMethods {
|
|
|
767
791
|
__name(this, "AdvancedMethods");
|
|
768
792
|
}
|
|
769
793
|
static getUsing(key, converter, fallback) {
|
|
770
|
-
const
|
|
771
|
-
if (!
|
|
794
|
+
const { key: resolvedKey, value } = this.resolveKeyInput(key);
|
|
795
|
+
if (!value) return fallback;
|
|
772
796
|
const hasFallback = fallback !== void 0;
|
|
773
|
-
const result = this.parser.convertValue(
|
|
797
|
+
const result = this.parser.convertValue(resolvedKey, fallback, converter, hasFallback);
|
|
774
798
|
return result;
|
|
775
799
|
}
|
|
776
800
|
getUsing(key, converter, fallback) {
|
|
@@ -778,13 +802,14 @@ var AdvancedMethods = class _AdvancedMethods extends PrimitiveMethods {
|
|
|
778
802
|
}
|
|
779
803
|
/**
|
|
780
804
|
* Get an environment variable using a custom converter function.
|
|
805
|
+
* Accepts a single key or an ordered list for automatic fallback.
|
|
781
806
|
*/
|
|
782
807
|
static getWith(key, converter, fallback) {
|
|
783
|
-
const
|
|
784
|
-
if (!
|
|
808
|
+
const { key: resolvedKey, value } = this.resolveKeyInput(key);
|
|
809
|
+
if (!value) return fallback;
|
|
785
810
|
const hasFallback = fallback !== void 0;
|
|
786
811
|
const result = this.parser.convertValue(
|
|
787
|
-
|
|
812
|
+
resolvedKey,
|
|
788
813
|
fallback,
|
|
789
814
|
converter,
|
|
790
815
|
hasFallback
|