ezcfg 0.2.0 → 0.3.1

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.
Files changed (46) hide show
  1. package/README.md +133 -64
  2. package/dist/computed-spec.d.ts +9 -0
  3. package/dist/computed-spec.d.ts.map +1 -0
  4. package/dist/computed-spec.js +20 -0
  5. package/dist/computed-spec.js.map +1 -0
  6. package/dist/config-spec.d.ts +10 -0
  7. package/dist/config-spec.d.ts.map +1 -0
  8. package/dist/config-spec.js +7 -0
  9. package/dist/config-spec.js.map +1 -0
  10. package/dist/database-config.d.ts +9 -0
  11. package/dist/database-config.d.ts.map +1 -0
  12. package/dist/database-config.js +2 -0
  13. package/dist/database-config.js.map +1 -0
  14. package/dist/define-config.d.ts +9 -0
  15. package/dist/define-config.d.ts.map +1 -0
  16. package/dist/define-config.js +45 -0
  17. package/dist/define-config.js.map +1 -0
  18. package/dist/env-spec.d.ts +18 -0
  19. package/dist/env-spec.d.ts.map +1 -0
  20. package/dist/env-spec.js +52 -0
  21. package/dist/env-spec.js.map +1 -0
  22. package/dist/errors.d.ts +5 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +9 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/index.d.ts +8 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +7 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/load-env-files.d.ts +5 -0
  31. package/dist/load-env-files.d.ts.map +1 -0
  32. package/dist/load-env-files.js +23 -0
  33. package/dist/load-env-files.js.map +1 -0
  34. package/dist/postgres-config-spec.d.ts +31 -0
  35. package/dist/postgres-config-spec.d.ts.map +1 -0
  36. package/dist/postgres-config-spec.js +43 -0
  37. package/dist/postgres-config-spec.js.map +1 -0
  38. package/dist/postgres-config.d.ts +43 -0
  39. package/dist/postgres-config.d.ts.map +1 -0
  40. package/dist/postgres-config.js +162 -0
  41. package/dist/postgres-config.js.map +1 -0
  42. package/dist/postgres.d.ts +3 -0
  43. package/dist/postgres.d.ts.map +1 -0
  44. package/dist/postgres.js +3 -0
  45. package/dist/postgres.js.map +1 -0
  46. package/package.json +42 -41
package/README.md CHANGED
@@ -9,8 +9,10 @@ Lite and easy configuration management for Node.js with full TypeScript support.
9
9
 
10
10
  - **Type-safe configuration** - Full TypeScript support with automatic type inference
11
11
  - **Automatic .env file loading** - Loads environment files based on `NODE_ENV`
12
+ - **Direct .env file parsing** - Read from a specific `.env` file without modifying `process.env`
12
13
  - **Validation with clear error messages** - Collects all validation errors at once
13
- - **Zero runtime dependencies** - Only uses `dotenv` for .env file parsing
14
+ - **PostgreSQL config support** - Built-in `postgresConfig` spec via `ezcfg/postgres`
15
+ - **Extensible** - Implement `ConfigSpec` to add custom config types
14
16
  - **Singleton pattern** - Config is lazily evaluated and cached (except in test environment)
15
17
 
16
18
  ## Installation
@@ -90,12 +92,40 @@ const config = getConfig(); // Lazily evaluated and cached
90
92
  | `schema` | `Record<string, unknown>` | Object defining your configuration shape |
91
93
  | `options.loadEnv` | `boolean` | Whether to load .env files automatically (default: `false`) |
92
94
  | `options.envLoader` | `() => void` | Custom function to load environment variables |
95
+ | `options.fromEnvFile` | `string` | Path to a `.env` file to parse directly (does not modify `process.env`) |
93
96
 
94
97
  **Behavior:**
95
98
 
96
99
  - Returns a factory function that lazily evaluates and caches the config
97
100
  - In test environment (`NODE_ENV=test`), config is re-evaluated on each call
98
101
  - Throws `ConfigValidationError` if any required values are missing
102
+ - When `fromEnvFile` is set, the file is parsed into a local object and passed to each spec's `resolve()` — `process.env` is never modified
103
+
104
+ ---
105
+
106
+ ### `parseEnvFile(filePath)`
107
+
108
+ Parses a `.env` file and returns its contents as a `Record<string, string>`. Does not modify `process.env`.
109
+
110
+ ```typescript
111
+ import { parseEnvFile } from 'ezcfg';
112
+
113
+ const env = parseEnvFile('/path/to/.env');
114
+ // { DATABASE_URL: 'postgres://...', API_KEY: 'secret' }
115
+ ```
116
+
117
+ Useful for injecting env vars into test runners:
118
+
119
+ ```typescript
120
+ // vitest.config.ts
121
+ import { parseEnvFile } from 'ezcfg';
122
+
123
+ export default defineConfig({
124
+ test: {
125
+ env: parseEnvFile(resolve(__dirname, '.env')),
126
+ },
127
+ });
128
+ ```
99
129
 
100
130
  ---
101
131
 
@@ -216,6 +246,90 @@ loadEnvFiles({
216
246
  });
217
247
  ```
218
248
 
249
+ ---
250
+
251
+ ## `ezcfg/postgres`
252
+
253
+ PostgreSQL configuration support, available as a subpath import.
254
+
255
+ ```typescript
256
+ import { postgresConfig, PostgresConfig } from 'ezcfg/postgres';
257
+ ```
258
+
259
+ ### `postgresConfig(prefix, mode?)`
260
+
261
+ A `ConfigSpec` implementation for PostgreSQL database configuration. Use with `defineConfig`.
262
+
263
+ ```typescript
264
+ import { defineConfig } from 'ezcfg';
265
+ import { postgresConfig } from 'ezcfg/postgres';
266
+
267
+ const getConfig = defineConfig({
268
+ db: postgresConfig('ORDER_DB'), // reads ORDER_DB_URL
269
+ db2: postgresConfig('PG', 'fields'), // reads PG_HOST, PG_PORT, etc.
270
+ });
271
+
272
+ getConfig().db.host; // "localhost"
273
+ getConfig().db.toString(); // "postgres://..."
274
+ ```
275
+
276
+ **Parameters:**
277
+
278
+ | Parameter | Type | Default | Description |
279
+ |-----------|------|---------|-------------|
280
+ | `prefix` | `string` | — | Environment variable prefix |
281
+ | `mode` | `"url" \| "fields"` | `"url"` | `"url"` reads `{PREFIX}_URL`, `"fields"` reads individual fields |
282
+
283
+ **Fields mode** reads: `{PREFIX}_HOST`, `{PREFIX}_PORT`, `{PREFIX}_DATABASE`, `{PREFIX}_USER`, `{PREFIX}_PASSWORD`
284
+
285
+ ### `PostgresConfig`
286
+
287
+ Immutable value object representing a PostgreSQL connection configuration.
288
+
289
+ ```typescript
290
+ import { PostgresConfig } from 'ezcfg/postgres';
291
+
292
+ // From URL
293
+ const config = PostgresConfig.fromUrl('postgres://user:pass@localhost:5432/mydb');
294
+
295
+ // From environment variables
296
+ const config = PostgresConfig.fromEnv('DATABASE'); // reads DATABASE_URL
297
+ const config = PostgresConfig.fromEnv('PG', { mode: 'fields' });
298
+
299
+ // Builder methods (each returns a new instance)
300
+ config.withDatabase('other_db');
301
+ config.withHost('remote-host');
302
+ config.withPort(5433);
303
+ config.withUser('admin');
304
+ config.withPassword('secret');
305
+ config.withPoolSize(10);
306
+ config.withConnectionTimeout(5000);
307
+ config.withIdleTimeout(30000);
308
+
309
+ // Connection string
310
+ config.toString(); // "postgres://user:pass@localhost:5432/mydb"
311
+ ```
312
+
313
+ ### Using with `fromEnvFile`
314
+
315
+ `postgresConfig` works with `fromEnvFile` — the `.env` file is parsed locally without modifying `process.env`:
316
+
317
+ ```typescript
318
+ import { defineConfig } from 'ezcfg';
319
+ import { postgresConfig } from 'ezcfg/postgres';
320
+
321
+ const getConfig = defineConfig(
322
+ { db: postgresConfig('DATABASE') },
323
+ { fromEnvFile: resolve(__dirname, '.env') }
324
+ );
325
+
326
+ // .env contains: DATABASE_URL=postgres://user@localhost/mydb
327
+ const config = getConfig();
328
+ config.db.database; // "mydb"
329
+ ```
330
+
331
+ ---
332
+
219
333
  ## .env File Loading
220
334
 
221
335
  When `loadEnv: true` is set, ezcfg automatically loads environment files in the following order (later files override earlier ones):
@@ -241,7 +355,7 @@ When `loadEnv: true` is set, ezcfg automatically loads environment files in the
241
355
  When validation fails, ezcfg throws a `ConfigValidationError` with all errors collected:
242
356
 
243
357
  ```typescript
244
- import { defineConfig, env, ConfigValidationError } from 'ezcfg';
358
+ import { defineConfig, env, envNumber, ConfigValidationError } from 'ezcfg';
245
359
 
246
360
  const getConfig = defineConfig({
247
361
  apiKey: env('API_KEY'),
@@ -297,7 +411,7 @@ const config = getConfig();
297
411
  You can also extract the config type for use elsewhere:
298
412
 
299
413
  ```typescript
300
- import { defineConfig, env, type InferConfigType } from 'ezcfg';
414
+ import { defineConfig, env, envNumber, type InferConfigType } from 'ezcfg';
301
415
 
302
416
  const schema = {
303
417
  apiKey: env('API_KEY'),
@@ -315,75 +429,30 @@ function initializeApp(config: AppConfig) {
315
429
  }
316
430
  ```
317
431
 
318
- ## Examples
319
-
320
- ### Database Configuration
321
-
322
- ```typescript
323
- import { defineConfig, env, envNumber, envOptional } from 'ezcfg';
324
-
325
- export const getDbConfig = defineConfig({
326
- host: env('DB_HOST'),
327
- port: envNumber('DB_PORT'),
328
- database: env('DB_NAME'),
329
- user: env('DB_USER'),
330
- password: envOptional('DB_PASSWORD'),
331
- }, { loadEnv: true });
332
-
333
- // Usage
334
- const db = getDbConfig();
335
- const connectionString = `postgres://${db.user}:${db.password}@${db.host}:${db.port}/${db.database}`;
336
- ```
432
+ ## Custom ConfigSpec
337
433
 
338
- ### API Service Configuration
434
+ Implement the `ConfigSpec` interface to create your own config types:
339
435
 
340
436
  ```typescript
341
- import { defineConfig, env, envNumber, envBoolean, envJsonOptional } from 'ezcfg';
342
-
343
- export const getConfig = defineConfig({
344
- // Server
345
- port: envNumber('PORT'),
346
- host: envOptional('HOST', '0.0.0.0'),
347
-
348
- // API Keys
349
- apiKey: env('API_KEY'),
350
- secretKey: env('SECRET_KEY'),
351
-
352
- // Features
353
- debug: envBoolean('DEBUG', false),
354
- enableMetrics: envBoolean('ENABLE_METRICS', true),
437
+ import type { ConfigSpec } from 'ezcfg';
355
438
 
356
- // CORS
357
- allowedOrigins: envJsonOptional<string[]>('ALLOWED_ORIGINS', ['http://localhost:3000']),
358
- }, { loadEnv: true });
359
- ```
439
+ class RedisConfigSpec implements ConfigSpec<RedisConfig> {
440
+ readonly _type = 'redis';
360
441
 
361
- ### Multi-environment Setup
442
+ constructor(private readonly prefix: string) {}
362
443
 
363
- ```
364
- project/
365
- ├── .env # Shared defaults
366
- ├── .env.local # Local secrets (gitignored)
367
- ├── .env.development # Development settings
368
- ├── .env.production # Production settings
369
- └── .env.test # Test settings
370
- ```
444
+ resolve(errors: string[], envSource?: Record<string, string>): RedisConfig | undefined {
445
+ const source = envSource ?? process.env;
446
+ const url = source[`${this.prefix}_URL`];
371
447
 
372
- ```bash
373
- # .env
374
- LOG_LEVEL=info
375
- API_TIMEOUT=5000
448
+ if (!url) {
449
+ errors.push(`Missing ${this.prefix}_URL`);
450
+ return undefined;
451
+ }
376
452
 
377
- # .env.development
378
- DEBUG=true
379
- API_URL=http://localhost:3000
380
-
381
- # .env.production
382
- DEBUG=false
383
- API_URL=https://api.example.com
384
-
385
- # .env.local (gitignored)
386
- API_KEY=your-secret-key
453
+ return new RedisConfig(url);
454
+ }
455
+ }
387
456
  ```
388
457
 
389
458
  ## License
@@ -0,0 +1,9 @@
1
+ import type { ConfigSpec } from "./config-spec.js";
2
+ export declare class ComputedSpec<T> implements ConfigSpec<T> {
3
+ private readonly factory;
4
+ readonly _type = "computed";
5
+ constructor(factory: () => T);
6
+ resolve(errors: string[], _envSource?: Record<string, string>): T | undefined;
7
+ }
8
+ export declare function computed<T>(factory: () => T): ComputedSpec<T>;
9
+ //# sourceMappingURL=computed-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computed-spec.d.ts","sourceRoot":"","sources":["../src/computed-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,qBAAa,YAAY,CAAC,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,CAAC;IAGrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,KAAK,cAAc;IAE5B,YAA6B,OAAO,EAAE,MAAM,CAAC,EAAI;IAEjD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAO5E;CACJ;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAE7D"}
@@ -0,0 +1,20 @@
1
+ export class ComputedSpec {
2
+ factory;
3
+ _type = "computed";
4
+ constructor(factory) {
5
+ this.factory = factory;
6
+ }
7
+ resolve(errors, _envSource) {
8
+ try {
9
+ return this.factory();
10
+ }
11
+ catch (e) {
12
+ errors.push(`Computed value failed: ${e.message}`);
13
+ return undefined;
14
+ }
15
+ }
16
+ }
17
+ export function computed(factory) {
18
+ return new ComputedSpec(factory);
19
+ }
20
+ //# sourceMappingURL=computed-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computed-spec.js","sourceRoot":"","sources":["../src/computed-spec.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,YAAY;IAGQ,OAAO;IAF3B,KAAK,GAAG,UAAU,CAAC;IAE5B,YAA6B,OAAgB,EAAE;uBAAlB,OAAO;IAAY,CAAC;IAEjD,OAAO,CAAC,MAAgB,EAAE,UAAmC,EAAiB;QAC1E,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,0BAA2B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,OAAO,SAAS,CAAC;QACrB,CAAC;IAAA,CACJ;CACJ;AAED,MAAM,UAAU,QAAQ,CAAI,OAAgB,EAAmB;IAC3D,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;AAAA,CACpC"}
@@ -0,0 +1,10 @@
1
+ export interface ConfigSpec<T> {
2
+ readonly _type: string;
3
+ resolve(errors: string[], envSource?: Record<string, string>): T | undefined;
4
+ }
5
+ export type InferSpecType<S> = S extends ConfigSpec<infer T> ? T : S;
6
+ export type InferConfigType<S extends Record<string, unknown>> = {
7
+ readonly [K in keyof S]: InferSpecType<S[K]>;
8
+ };
9
+ export declare function isConfigSpec(value: unknown): value is ConfigSpec<unknown>;
10
+ //# sourceMappingURL=config-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-spec.d.ts","sourceRoot":"","sources":["../src/config-spec.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;CAChF;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAErE,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC7D,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/C,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,CAOzE"}
@@ -0,0 +1,7 @@
1
+ export function isConfigSpec(value) {
2
+ return (typeof value === "object" &&
3
+ value !== null &&
4
+ "resolve" in value &&
5
+ typeof value.resolve === "function");
6
+ }
7
+ //# sourceMappingURL=config-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-spec.js","sourceRoot":"","sources":["../src/config-spec.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,YAAY,CAAC,KAAc,EAAgC;IACvE,OAAO,CACH,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,SAAS,IAAI,KAAK;QAClB,OAAQ,KAA6B,CAAC,OAAO,KAAK,UAAU,CAC/D,CAAC;AAAA,CACL"}
@@ -0,0 +1,9 @@
1
+ export interface DatabaseConfig {
2
+ readonly host: string;
3
+ readonly port: number;
4
+ readonly database: string;
5
+ readonly user: string;
6
+ readonly password?: string;
7
+ toString(): string;
8
+ }
9
+ //# sourceMappingURL=database-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-config.d.ts","sourceRoot":"","sources":["../src/database-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,IAAI,MAAM,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=database-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-config.js","sourceRoot":"","sources":["../src/database-config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { type InferConfigType } from "./config-spec.js";
2
+ export interface ConfigOptions {
3
+ loadEnv?: boolean;
4
+ envLoader?: () => void;
5
+ fromEnvFile?: string;
6
+ }
7
+ export declare function defineConfig<S extends Record<string, unknown>>(schema: S, options?: ConfigOptions): () => InferConfigType<S>;
8
+ export declare function parseEnvFile(filePath: string): Record<string, string>;
9
+ //# sourceMappingURL=define-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-config.d.ts","sourceRoot":"","sources":["../src/define-config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAgB,MAAM,kBAAkB,CAAC;AAItE,MAAM,WAAW,aAAa;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1D,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,aAAa,GACxB,MAAM,eAAe,CAAC,CAAC,CAAC,CAsC1B;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGrE"}
@@ -0,0 +1,45 @@
1
+ import fs from "node:fs";
2
+ import dotenv from "dotenv";
3
+ import { isConfigSpec } from "./config-spec.js";
4
+ import { ConfigValidationError } from "./errors.js";
5
+ import { loadEnvFiles } from "./load-env-files.js";
6
+ export function defineConfig(schema, options) {
7
+ let instance = null;
8
+ return () => {
9
+ if (instance && process.env.NODE_ENV !== "test") {
10
+ return instance;
11
+ }
12
+ let envSource;
13
+ if (options?.fromEnvFile) {
14
+ envSource = parseEnvFile(options.fromEnvFile);
15
+ }
16
+ else if (options?.loadEnv) {
17
+ if (options.envLoader) {
18
+ options.envLoader();
19
+ }
20
+ else {
21
+ loadEnvFiles();
22
+ }
23
+ }
24
+ const config = {};
25
+ const errors = [];
26
+ for (const [key, value] of Object.entries(schema)) {
27
+ if (isConfigSpec(value)) {
28
+ config[key] = value.resolve(errors, envSource);
29
+ }
30
+ else {
31
+ config[key] = value;
32
+ }
33
+ }
34
+ if (errors.length > 0) {
35
+ throw new ConfigValidationError(errors);
36
+ }
37
+ instance = config;
38
+ return instance;
39
+ };
40
+ }
41
+ export function parseEnvFile(filePath) {
42
+ const content = fs.readFileSync(filePath, "utf-8");
43
+ return dotenv.parse(content);
44
+ }
45
+ //# sourceMappingURL=define-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-config.js","sourceRoot":"","sources":["../src/define-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAwB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQnD,MAAM,UAAU,YAAY,CACxB,MAAS,EACT,OAAuB,EACC;IACxB,IAAI,QAAQ,GAA8B,IAAI,CAAC;IAE/C,OAAO,GAAG,EAAE,CAAC;QACT,IAAI,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC9C,OAAO,QAAQ,CAAC;QACpB,CAAC;QAED,IAAI,SAA6C,CAAC;QAElD,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;YACvB,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YAC1B,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACpB,OAAO,CAAC,SAAS,EAAE,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACJ,YAAY,EAAE,CAAC;YACnB,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAAG,EAA6B,CAAC;QAC7C,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;QACL,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,QAAQ,GAAG,MAA4B,CAAC;QACxC,OAAO,QAAQ,CAAC;IAAA,CACnB,CAAC;AAAA,CACL;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAA0B;IACnE,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAAA,CAChC"}
@@ -0,0 +1,18 @@
1
+ import type { ConfigSpec } from "./config-spec.js";
2
+ export declare class EnvSpec<T> implements ConfigSpec<T> {
3
+ private readonly envKey;
4
+ private readonly required;
5
+ private readonly defaultValue?;
6
+ private readonly transform?;
7
+ readonly _type = "env";
8
+ constructor(envKey: string, required: boolean, defaultValue?: T | undefined, transform?: ((value: string) => T) | undefined);
9
+ resolve(errors: string[], envSource?: Record<string, string>): T | undefined;
10
+ }
11
+ export declare function env(key: string): EnvSpec<string>;
12
+ export declare function envOptional(key: string, defaultValue?: string): EnvSpec<string | undefined>;
13
+ export declare function envNumber(key: string): EnvSpec<number>;
14
+ export declare function envNumberOptional(key: string, defaultValue?: number): EnvSpec<number | undefined>;
15
+ export declare function envBoolean(key: string, defaultValue?: boolean): EnvSpec<boolean>;
16
+ export declare function envJson<T>(key: string): EnvSpec<T>;
17
+ export declare function envJsonOptional<T>(key: string, defaultValue?: T): EnvSpec<T | undefined>;
18
+ //# sourceMappingURL=env-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-spec.d.ts","sourceRoot":"","sources":["../src/env-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,qBAAa,OAAO,CAAC,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,CAAC;IAIxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAN/B,QAAQ,CAAC,KAAK,SAAS;IAEvB,YACqB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,EACjB,YAAY,CAAC,eAAG,EAChB,SAAS,CAAC,oCAAsB,EACjD;IAEJ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAkB3E;CACJ;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEhD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE3F;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEjG;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9E;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAElD;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAExF"}
@@ -0,0 +1,52 @@
1
+ export class EnvSpec {
2
+ envKey;
3
+ required;
4
+ defaultValue;
5
+ transform;
6
+ _type = "env";
7
+ constructor(envKey, required, defaultValue, transform) {
8
+ this.envKey = envKey;
9
+ this.required = required;
10
+ this.defaultValue = defaultValue;
11
+ this.transform = transform;
12
+ }
13
+ resolve(errors, envSource) {
14
+ const rawValue = (envSource ?? process.env)[this.envKey];
15
+ if (!rawValue && this.required) {
16
+ errors.push(`Missing required env: ${this.envKey}`);
17
+ return undefined;
18
+ }
19
+ if (rawValue !== undefined) {
20
+ try {
21
+ return this.transform ? this.transform(rawValue) : rawValue;
22
+ }
23
+ catch (e) {
24
+ errors.push(`Failed to transform ${this.envKey}: ${e.message}`);
25
+ return undefined;
26
+ }
27
+ }
28
+ return this.defaultValue;
29
+ }
30
+ }
31
+ export function env(key) {
32
+ return new EnvSpec(key, true);
33
+ }
34
+ export function envOptional(key, defaultValue) {
35
+ return new EnvSpec(key, false, defaultValue);
36
+ }
37
+ export function envNumber(key) {
38
+ return new EnvSpec(key, true, undefined, Number);
39
+ }
40
+ export function envNumberOptional(key, defaultValue) {
41
+ return new EnvSpec(key, false, defaultValue, (v) => (v ? Number(v) : undefined));
42
+ }
43
+ export function envBoolean(key, defaultValue = false) {
44
+ return new EnvSpec(key, false, defaultValue, (v) => v === "true" || v === "1");
45
+ }
46
+ export function envJson(key) {
47
+ return new EnvSpec(key, true, undefined, JSON.parse);
48
+ }
49
+ export function envJsonOptional(key, defaultValue) {
50
+ return new EnvSpec(key, false, defaultValue, (v) => (v ? JSON.parse(v) : undefined));
51
+ }
52
+ //# sourceMappingURL=env-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-spec.js","sourceRoot":"","sources":["../src/env-spec.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,OAAO;IAIK,MAAM;IACN,QAAQ;IACR,YAAY;IACZ,SAAS;IANrB,KAAK,GAAG,KAAK,CAAC;IAEvB,YACqB,MAAc,EACd,QAAiB,EACjB,YAAgB,EAChB,SAAgC,EACnD;sBAJmB,MAAM;wBACN,QAAQ;4BACR,YAAY;yBACZ,SAAS;IAC3B,CAAC;IAEJ,OAAO,CAAC,MAAgB,EAAE,SAAkC,EAAiB;QACzE,MAAM,QAAQ,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEzD,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACpD,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC;gBACD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,QAAc,CAAC;YACvE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,MAAM,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,MAAM,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC3E,OAAO,SAAS,CAAC;YACrB,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC,YAAY,CAAC;IAAA,CAC5B;CACJ;AAED,MAAM,UAAU,GAAG,CAAC,GAAW,EAAmB;IAC9C,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAAA,CACjC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,YAAqB,EAA+B;IACzF,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;AAAA,CAChD;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAmB;IACpD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AAAA,CACpD;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,YAAqB,EAA+B;IAC/F,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAAA,CACpF;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,YAAY,GAAG,KAAK,EAAoB;IAC5E,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AAAA,CAClF;AAED,MAAM,UAAU,OAAO,CAAI,GAAW,EAAc;IAChD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AAAA,CACxD;AAED,MAAM,UAAU,eAAe,CAAI,GAAW,EAAE,YAAgB,EAA0B;IACtF,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAAA,CACxF"}
@@ -0,0 +1,5 @@
1
+ export declare class ConfigValidationError extends Error {
2
+ readonly errors: string[];
3
+ constructor(errors: string[]);
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,qBAAsB,SAAQ,KAAK;aAChB,MAAM,EAAE,MAAM,EAAE;IAA5C,YAA4B,MAAM,EAAE,MAAM,EAAE,EAG3C;CACJ"}
package/dist/errors.js ADDED
@@ -0,0 +1,9 @@
1
+ export class ConfigValidationError extends Error {
2
+ errors;
3
+ constructor(errors) {
4
+ super(`Config validation failed:\n - ${errors.join("\n - ")}`);
5
+ this.errors = errors;
6
+ this.name = "ConfigValidationError";
7
+ }
8
+ }
9
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAChB,MAAM;IAAlC,YAA4B,MAAgB,EAAE;QAC1C,KAAK,CAAC,kCAAkC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;sBADzC,MAAM;QAE9B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IAAA,CACvC;CACJ"}
@@ -0,0 +1,8 @@
1
+ export { type ConfigSpec, type InferSpecType, type InferConfigType, isConfigSpec, } from "./config-spec.js";
2
+ export { ConfigValidationError } from "./errors.js";
3
+ export { defineConfig, parseEnvFile, type ConfigOptions } from "./define-config.js";
4
+ export { loadEnvFiles } from "./load-env-files.js";
5
+ export { EnvSpec, env, envOptional, envNumber, envNumberOptional, envBoolean, envJson, envJsonOptional, } from "./env-spec.js";
6
+ export { ComputedSpec, computed } from "./computed-spec.js";
7
+ export type { DatabaseConfig } from "./database-config.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,YAAY,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EACH,OAAO,EACP,GAAG,EACH,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE5D,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { isConfigSpec, } from "./config-spec.js";
2
+ export { ConfigValidationError } from "./errors.js";
3
+ export { defineConfig, parseEnvFile } from "./define-config.js";
4
+ export { loadEnvFiles } from "./load-env-files.js";
5
+ export { EnvSpec, env, envOptional, envNumber, envNumberOptional, envBoolean, envJson, envJsonOptional, } from "./env-spec.js";
6
+ export { ComputedSpec, computed } from "./computed-spec.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,YAAY,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAsB,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EACH,OAAO,EACP,GAAG,EACH,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,eAAe,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function loadEnvFiles({ basePath, nodeEnv }?: {
2
+ basePath?: string;
3
+ nodeEnv?: string;
4
+ }): void;
5
+ //# sourceMappingURL=load-env-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env-files.d.ts","sourceRoot":"","sources":["../src/load-env-files.ts"],"names":[],"mappings":"AAKA,wBAAgB,YAAY,CAAC,EACzB,QAAQ,EACR,OAAO,EACV,GAAE;IACC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAqBZ"}
@@ -0,0 +1,23 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import dotenv from "dotenv";
4
+ export function loadEnvFiles({ basePath, nodeEnv, } = {}) {
5
+ const basePath_ = basePath ?? process.cwd();
6
+ const nodeEnv_ = nodeEnv ?? process.env.NODE_ENV ?? "development";
7
+ const envFiles = [
8
+ ".env",
9
+ ".env.local",
10
+ `.env.${nodeEnv_}`,
11
+ `.env.${nodeEnv_}.local`,
12
+ ];
13
+ const loadEnvFile = (filePath) => {
14
+ if (fs.existsSync(filePath)) {
15
+ dotenv.config({ path: filePath });
16
+ }
17
+ };
18
+ envFiles.reverse().forEach((file) => {
19
+ const filePath = path.resolve(basePath_, file);
20
+ loadEnvFile(filePath);
21
+ });
22
+ }
23
+ //# sourceMappingURL=load-env-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env-files.js","sourceRoot":"","sources":["../src/load-env-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,UAAU,YAAY,CAAC,EACzB,QAAQ,EACR,OAAO,GACV,GAGG,EAAE,EAAQ;IACV,MAAM,SAAS,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;IAElE,MAAM,QAAQ,GAAG;QACb,MAAM;QACN,YAAY;QACZ,QAAQ,QAAQ,EAAE;QAClB,QAAQ,QAAQ,QAAQ;KAC3B,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC;QACtC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;IAAA,CACJ,CAAC;IAEF,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/C,WAAW,CAAC,QAAQ,CAAC,CAAC;IAAA,CACzB,CAAC,CAAC;AAAA,CACN"}
@@ -0,0 +1,31 @@
1
+ import type { ConfigSpec } from "./config-spec.js";
2
+ import { PostgresConfig, type FromEnvOptions } from "./postgres-config.js";
3
+ export declare class PostgresConfigSpec implements ConfigSpec<PostgresConfig> {
4
+ private readonly prefix;
5
+ private readonly mode;
6
+ readonly _type = "postgres";
7
+ constructor(prefix: string, mode?: FromEnvOptions["mode"]);
8
+ resolve(errors: string[], envSource?: Record<string, string>): PostgresConfig | undefined;
9
+ }
10
+ /**
11
+ * PostgreSQL database configuration from environment variables.
12
+ * Returns a PostgresConfig instance.
13
+ *
14
+ * @param prefix - Environment variable prefix
15
+ * @param mode - "url" reads {PREFIX}_URL, "fields" reads individual fields
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { defineConfig, postgresConfig } from "ezcfg";
20
+ *
21
+ * const getConfig = defineConfig({
22
+ * db: postgresConfig("ORDER_DB"), // reads ORDER_DB_URL
23
+ * db2: postgresConfig("PG", "fields"), // reads PG_HOST, PG_PORT, etc.
24
+ * });
25
+ *
26
+ * getConfig().db.host; // "localhost"
27
+ * getConfig().db.toString(); // "postgres://..."
28
+ * ```
29
+ */
30
+ export declare function postgresConfig(prefix: string, mode?: FromEnvOptions["mode"]): PostgresConfigSpec;
31
+ //# sourceMappingURL=postgres-config-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-config-spec.d.ts","sourceRoot":"","sources":["../src/postgres-config-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3E,qBAAa,kBAAmB,YAAW,UAAU,CAAC,cAAc,CAAC;IAI7D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJzB,QAAQ,CAAC,KAAK,cAAc;IAE5B,YACqB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAc,CAAC,MAAM,CAAS,EACrD;IAEJ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,GAAG,SAAS,CAOxF;CACJ;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAc,CAAC,MAAM,CAAS,GACrC,kBAAkB,CAEpB"}
@@ -0,0 +1,43 @@
1
+ import { PostgresConfig } from "./postgres-config.js";
2
+ export class PostgresConfigSpec {
3
+ prefix;
4
+ mode;
5
+ _type = "postgres";
6
+ constructor(prefix, mode = "url") {
7
+ this.prefix = prefix;
8
+ this.mode = mode;
9
+ }
10
+ resolve(errors, envSource) {
11
+ try {
12
+ return PostgresConfig.fromEnv(this.prefix, { mode: this.mode }, envSource);
13
+ }
14
+ catch (e) {
15
+ errors.push(e.message);
16
+ return undefined;
17
+ }
18
+ }
19
+ }
20
+ /**
21
+ * PostgreSQL database configuration from environment variables.
22
+ * Returns a PostgresConfig instance.
23
+ *
24
+ * @param prefix - Environment variable prefix
25
+ * @param mode - "url" reads {PREFIX}_URL, "fields" reads individual fields
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { defineConfig, postgresConfig } from "ezcfg";
30
+ *
31
+ * const getConfig = defineConfig({
32
+ * db: postgresConfig("ORDER_DB"), // reads ORDER_DB_URL
33
+ * db2: postgresConfig("PG", "fields"), // reads PG_HOST, PG_PORT, etc.
34
+ * });
35
+ *
36
+ * getConfig().db.host; // "localhost"
37
+ * getConfig().db.toString(); // "postgres://..."
38
+ * ```
39
+ */
40
+ export function postgresConfig(prefix, mode = "url") {
41
+ return new PostgresConfigSpec(prefix, mode);
42
+ }
43
+ //# sourceMappingURL=postgres-config-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-config-spec.js","sourceRoot":"","sources":["../src/postgres-config-spec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAuB,MAAM,sBAAsB,CAAC;AAE3E,MAAM,OAAO,kBAAkB;IAIN,MAAM;IACN,IAAI;IAJhB,KAAK,GAAG,UAAU,CAAC;IAE5B,YACqB,MAAc,EACd,IAAI,GAA2B,KAAK,EACvD;sBAFmB,MAAM;oBACN,IAAI;IACtB,CAAC;IAEJ,OAAO,CAAC,MAAgB,EAAE,SAAkC,EAA8B;QACtF,IAAI,CAAC;YACD,OAAO,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,SAAS,CAAC;QACrB,CAAC;IAAA,CACJ;CACJ;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,cAAc,CAC1B,MAAc,EACd,IAAI,GAA2B,KAAK,EAClB;IAClB,OAAO,IAAI,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAAA,CAC/C"}
@@ -0,0 +1,43 @@
1
+ import type { DatabaseConfig } from "./database-config.js";
2
+ export interface PoolOptions {
3
+ size?: number;
4
+ connectionTimeout?: number;
5
+ idleTimeout?: number;
6
+ }
7
+ export interface FromEnvOptions {
8
+ /**
9
+ * Environment variable loading mode.
10
+ * - "url": Load from {PREFIX}_URL (default)
11
+ * - "fields": Load from {PREFIX}_HOST, {PREFIX}_PORT, {PREFIX}_DATABASE, {PREFIX}_USER, {PREFIX}_PASSWORD
12
+ */
13
+ mode?: "url" | "fields";
14
+ }
15
+ export declare class PostgresConfig implements DatabaseConfig {
16
+ readonly host: string;
17
+ readonly database: string;
18
+ readonly user: string;
19
+ readonly port: number;
20
+ readonly password?: string;
21
+ readonly pool?: PoolOptions;
22
+ constructor(config: {
23
+ database: string;
24
+ user?: string;
25
+ host?: string;
26
+ port?: number;
27
+ password?: string;
28
+ pool?: PoolOptions;
29
+ });
30
+ static fromUrl(value: string): PostgresConfig;
31
+ static fromEnv(prefix: string, options?: FromEnvOptions, envSource?: Record<string, string>): PostgresConfig;
32
+ private static parseUrl;
33
+ withDatabase(database: string): PostgresConfig;
34
+ withUser(user: string): PostgresConfig;
35
+ withPassword(password: string): PostgresConfig;
36
+ withHost(host: string): PostgresConfig;
37
+ withPort(port: number): PostgresConfig;
38
+ withPoolSize(size: number): PostgresConfig;
39
+ withConnectionTimeout(connectionTimeout: number): PostgresConfig;
40
+ withIdleTimeout(idleTimeout: number): PostgresConfig;
41
+ toString(): string;
42
+ }
43
+ //# sourceMappingURL=postgres-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-config.d.ts","sourceRoot":"","sources":["../src/postgres-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,WAAW;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC3B;AAED,qBAAa,cAAe,YAAW,cAAc;IACjD,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,IAAI,CAAC,EAAE,WAAW,CAAC;IAEnC,YAAY,MAAM,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,WAAW,CAAC;KACtB,EAOA;IAED,OAAc,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAEnD;IAED,OAAc,OAAO,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,cAAc,CAgChB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ;IAqBhB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CASpD;IAEM,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAS5C;IAEM,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CASpD;IAEM,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAS5C;IAEM,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAS5C;IAEM,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAShD;IAEM,qBAAqB,CAAC,iBAAiB,EAAE,MAAM,GAAG,cAAc,CAStE;IAEM,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAS1D;IAEM,QAAQ,IAAI,MAAM,CA0BxB;CACJ"}
@@ -0,0 +1,162 @@
1
+ export class PostgresConfig {
2
+ host;
3
+ database;
4
+ user;
5
+ port;
6
+ password;
7
+ pool;
8
+ constructor(config) {
9
+ this.database = config.database;
10
+ this.password = config.password;
11
+ this.host = config.host ?? "localhost";
12
+ this.user = config.user ?? "postgres";
13
+ this.port = config.port ?? 5432;
14
+ this.pool = config.pool;
15
+ }
16
+ static fromUrl(value) {
17
+ return new PostgresConfig(PostgresConfig.parseUrl(value));
18
+ }
19
+ static fromEnv(prefix, options, envSource) {
20
+ const source = envSource ?? process.env;
21
+ const mode = options?.mode ?? "url";
22
+ if (mode === "url") {
23
+ const envKey = `${prefix}_URL`;
24
+ const url = source[envKey];
25
+ if (!url) {
26
+ throw new Error(`Environment variable ${envKey} is not set`);
27
+ }
28
+ return PostgresConfig.fromUrl(url);
29
+ }
30
+ // fields mode
31
+ const database = source[`${prefix}_DATABASE`];
32
+ if (!database) {
33
+ throw new Error(`Environment variable ${prefix}_DATABASE is not set`);
34
+ }
35
+ return new PostgresConfig({
36
+ database,
37
+ host: source[`${prefix}_HOST`],
38
+ port: source[`${prefix}_PORT`]
39
+ ? parseInt(source[`${prefix}_PORT`])
40
+ : undefined,
41
+ user: source[`${prefix}_USER`],
42
+ password: source[`${prefix}_PASSWORD`],
43
+ });
44
+ }
45
+ static parseUrl(value) {
46
+ const regex = /postgres(ql)?:\/\/(?<user>[^:/]+)(:(?<password>[^@]+))?@(?<host>[^:/]+)(:(?<port>\d+))?\/(?<database>.+)/;
47
+ const matches = value.match(regex);
48
+ if (!matches?.groups) {
49
+ throw new Error(`Invalid postgres url: ${value}`);
50
+ }
51
+ const { user, password, host, port, database } = matches.groups;
52
+ return {
53
+ host,
54
+ database,
55
+ user,
56
+ port: port ? parseInt(port) : 5432,
57
+ password,
58
+ };
59
+ }
60
+ withDatabase(database) {
61
+ return new PostgresConfig({
62
+ host: this.host,
63
+ database,
64
+ user: this.user,
65
+ port: this.port,
66
+ password: this.password,
67
+ pool: this.pool,
68
+ });
69
+ }
70
+ withUser(user) {
71
+ return new PostgresConfig({
72
+ host: this.host,
73
+ database: this.database,
74
+ user,
75
+ port: this.port,
76
+ password: this.password,
77
+ pool: this.pool,
78
+ });
79
+ }
80
+ withPassword(password) {
81
+ return new PostgresConfig({
82
+ host: this.host,
83
+ database: this.database,
84
+ user: this.user,
85
+ port: this.port,
86
+ password,
87
+ pool: this.pool,
88
+ });
89
+ }
90
+ withHost(host) {
91
+ return new PostgresConfig({
92
+ host,
93
+ database: this.database,
94
+ user: this.user,
95
+ port: this.port,
96
+ password: this.password,
97
+ pool: this.pool,
98
+ });
99
+ }
100
+ withPort(port) {
101
+ return new PostgresConfig({
102
+ host: this.host,
103
+ database: this.database,
104
+ user: this.user,
105
+ port,
106
+ password: this.password,
107
+ pool: this.pool,
108
+ });
109
+ }
110
+ withPoolSize(size) {
111
+ return new PostgresConfig({
112
+ host: this.host,
113
+ database: this.database,
114
+ user: this.user,
115
+ port: this.port,
116
+ password: this.password,
117
+ pool: { ...this.pool, size },
118
+ });
119
+ }
120
+ withConnectionTimeout(connectionTimeout) {
121
+ return new PostgresConfig({
122
+ host: this.host,
123
+ database: this.database,
124
+ user: this.user,
125
+ port: this.port,
126
+ password: this.password,
127
+ pool: { ...this.pool, connectionTimeout },
128
+ });
129
+ }
130
+ withIdleTimeout(idleTimeout) {
131
+ return new PostgresConfig({
132
+ host: this.host,
133
+ database: this.database,
134
+ user: this.user,
135
+ port: this.port,
136
+ password: this.password,
137
+ pool: { ...this.pool, idleTimeout },
138
+ });
139
+ }
140
+ toString() {
141
+ let url = `postgres://${this.user}`;
142
+ if (this.password) {
143
+ url += `:${this.password}`;
144
+ }
145
+ url += `@${this.host}:${this.port}/${this.database}`;
146
+ const queryParams = [];
147
+ if (this.pool?.size !== undefined) {
148
+ queryParams.push(`pool_size=${this.pool.size}`);
149
+ }
150
+ if (this.pool?.connectionTimeout !== undefined) {
151
+ queryParams.push(`connection_timeout=${this.pool.connectionTimeout}`);
152
+ }
153
+ if (this.pool?.idleTimeout !== undefined) {
154
+ queryParams.push(`idle_timeout=${this.pool.idleTimeout}`);
155
+ }
156
+ if (queryParams.length > 0) {
157
+ url += `?${queryParams.join("&")}`;
158
+ }
159
+ return url;
160
+ }
161
+ }
162
+ //# sourceMappingURL=postgres-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-config.js","sourceRoot":"","sources":["../src/postgres-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { PostgresConfig, type PoolOptions, type FromEnvOptions, } from "./postgres-config.js";
2
+ export { PostgresConfigSpec, postgresConfig } from "./postgres-config-spec.js";
3
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../src/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,cAAc,GACtB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { PostgresConfig, } from "./postgres-config.js";
2
+ export { PostgresConfigSpec, postgresConfig } from "./postgres-config-spec.js";
3
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../src/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,cAAc,GAGjB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
package/package.json CHANGED
@@ -1,43 +1,44 @@
1
1
  {
2
- "name": "ezcfg",
3
- "version": "0.2.0",
4
- "description": "Lite and easy configuration management for Node.js",
5
- "license": "MIT",
6
- "author": "Sangwoo Hyun <wkdny.hyun@gmail.com>",
7
- "main": "./dist/index.js",
8
- "module": "./dist/index.mjs",
9
- "types": "./dist/index.d.ts",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/index.mjs",
14
- "require": "./dist/index.js"
15
- }
2
+ "name": "ezcfg",
3
+ "version": "0.3.1",
4
+ "type": "module",
5
+ "description": "Lite and easy configuration management for Node.js",
6
+ "license": "MIT",
7
+ "author": "Sangwoo Hyun <wkdny.hyun@gmail.com>",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
16
12
  },
17
- "files": [
18
- "dist",
19
- "LICENSE"
20
- ],
21
- "scripts": {
22
- "build": "tsup",
23
- "test": "vitest run",
24
- "test:watch": "vitest"
25
- },
26
- "dependencies": {
27
- "dotenv": "^17.2.3"
28
- },
29
- "devDependencies": {
30
- "@types/node": "^25.1.0",
31
- "tsup": "^8.5.1",
32
- "typescript": "^5.9.3",
33
- "vitest": "^4.0.18"
34
- },
35
- "keywords": [
36
- "config",
37
- "configuration",
38
- "env",
39
- "environment",
40
- "typescript",
41
- "type-safe"
42
- ]
43
- }
13
+ "./postgres": {
14
+ "types": "./dist/postgres.d.ts",
15
+ "import": "./dist/postgres.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "LICENSE"
21
+ ],
22
+ "dependencies": {
23
+ "dotenv": "^17.2.3"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^25.1.0",
27
+ "@typescript/native-preview": "^7.0.0-dev",
28
+ "typescript": "^5.9.3",
29
+ "vitest": "^4.0.18"
30
+ },
31
+ "keywords": [
32
+ "config",
33
+ "configuration",
34
+ "env",
35
+ "environment",
36
+ "typescript",
37
+ "type-safe"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsgo -p tsconfig.json",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest"
43
+ }
44
+ }