@pawells/config 2.3.1 → 3.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 +252 -149
- package/dist/errors.d.ts +24 -32
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +34 -37
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/manager.d.ts +265 -46
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +667 -137
- package/dist/manager.js.map +1 -1
- package/dist/provider.d.ts +280 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +108 -0
- package/dist/provider.js.map +1 -0
- package/dist/schema.factory.d.ts +30 -37
- package/dist/schema.factory.d.ts.map +1 -1
- package/dist/schema.factory.js +59 -92
- package/dist/schema.factory.js.map +1 -1
- package/dist/secret.d.ts +13 -2
- package/dist/secret.d.ts.map +1 -1
- package/dist/secret.js +31 -6
- package/dist/secret.js.map +1 -1
- package/package.json +63 -49
- package/CHANGELOG.md +0 -19
package/README.md
CHANGED
|
@@ -1,206 +1,309 @@
|
|
|
1
1
|
# @pawells/config
|
|
2
2
|
|
|
3
|
-
[](https://github.com/PhillipAWells/config/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@pawells/config)
|
|
4
5
|
[](https://nodejs.org)
|
|
5
|
-
[](./LICENSE)
|
|
6
|
+
[](../../LICENSE)
|
|
7
7
|
|
|
8
8
|
## Description
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
`@pawells/config` is the core package of the `@pawells/config-workspace` suite. It provides:
|
|
11
|
+
|
|
12
|
+
- A **global singleton** (`ConfigManager`) and an **instance-based** (`ScopedConfigManager`) configuration manager, both backed by [Zod](https://zod.dev) schema validation.
|
|
13
|
+
- A **schema factory** (`RegisterConfigSchema`) that derives typed, namespaced accessor objects from a Zod object schema, eliminating the need to call `ConfigManager.Register` for every key individually.
|
|
14
|
+
- A **`Secret()` wrapper** that marks Zod field schemas as sensitive — secret values are automatically redacted in templates and error messages.
|
|
15
|
+
- An **abstract base class** (`ConfigProvider`) and two interfaces (`IConfigProvider`, `ISyncConfigProvider`) for building custom providers.
|
|
16
|
+
- A structured **error hierarchy** rooted at `ConfigError`.
|
|
17
|
+
|
|
18
|
+
Values are resolved through a three-tier precedence model:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Registered defaults < Provider values < Runtime overrides (Set)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
See the [workspace README](../../README.md) for an end-to-end quick start. See [CHANGELOG.md](../../CHANGELOG.md) for version history.
|
|
11
25
|
|
|
12
26
|
## Requirements
|
|
13
27
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- **zod**: ^4.4.3 (peer dependency, required at runtime for schema validation)
|
|
28
|
+
- Node.js `>=22.0.0`
|
|
29
|
+
- `zod` `^4.4.3` (peer dependency, installed automatically)
|
|
17
30
|
|
|
18
31
|
## Installation
|
|
19
32
|
|
|
20
|
-
|
|
33
|
+
```sh
|
|
34
|
+
yarn add @pawells/config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
21
38
|
|
|
22
|
-
```
|
|
23
|
-
|
|
39
|
+
```typescript
|
|
40
|
+
import { z } from 'zod';
|
|
41
|
+
import { ConfigManager, RegisterConfigSchema, Secret } from '@pawells/config';
|
|
42
|
+
import { ConfigEnvironmentProvider } from '@pawells/config-provider-env';
|
|
43
|
+
|
|
44
|
+
// 1. Register providers BEFORE importing schema modules.
|
|
45
|
+
// Provider values are merged into schemas at registration time.
|
|
46
|
+
await ConfigEnvironmentProvider.Register({ path: '.env' });
|
|
47
|
+
|
|
48
|
+
// 2. Define and register a schema.
|
|
49
|
+
// The prefix 'DATABASE_' is derived from the name 'Database'.
|
|
50
|
+
const DatabaseConfig = RegisterConfigSchema('Database', z.object({
|
|
51
|
+
HOST: z.string().min(1).default('localhost'),
|
|
52
|
+
PORT: z.coerce.number().int().positive().default(5432),
|
|
53
|
+
PASSWORD: Secret(z.string().min(1)).default(''),
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
// 3. Retrieve validated, typed values.
|
|
57
|
+
const host = DatabaseConfig.Get('HOST'); // string
|
|
58
|
+
const port = DatabaseConfig.Get('PORT'); // number
|
|
59
|
+
|
|
60
|
+
// 4. Redact secrets for safe logging.
|
|
61
|
+
console.log(DatabaseConfig.Redact());
|
|
62
|
+
// → { HOST: 'localhost', PORT: 5432, PASSWORD: '***' }
|
|
24
63
|
```
|
|
25
64
|
|
|
26
|
-
|
|
65
|
+
## API Reference
|
|
27
66
|
|
|
28
|
-
|
|
29
|
-
|
|
67
|
+
### `RegisterConfigSchema(name, schema)`
|
|
68
|
+
|
|
69
|
+
Registers all fields of a Zod object schema with `ConfigManager` and returns a typed accessor object.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
function RegisterConfigSchema<TSchema extends z.ZodRawShape>(
|
|
73
|
+
name: string,
|
|
74
|
+
schema: z.ZodObject<TSchema>
|
|
75
|
+
): IConfigSchemaObject<z.infer<typeof schema>>
|
|
30
76
|
```
|
|
31
77
|
|
|
32
|
-
|
|
78
|
+
- `name` — Human-readable namespace. The env-var prefix is derived as `name.toUpperCase() + '_'` (e.g. `'Database'` → `DATABASE_`).
|
|
79
|
+
- `schema` — A `z.object(...)` schema. Every field should declare a `.default(...)` value.
|
|
33
80
|
|
|
34
|
-
|
|
81
|
+
**Returns** an `IConfigSchemaObject` with the following members:
|
|
35
82
|
|
|
36
|
-
|
|
83
|
+
| Member | Signature | Description |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `name` | `string` | The namespace name passed to `RegisterConfigSchema`. |
|
|
86
|
+
| `Get` | `Get<K>(key: K): TConfig[K]` | Retrieve the typed, validated value for `key`. Resolves DEFAULT → providers → OVERRIDE. |
|
|
87
|
+
| `Set` | `Set<K>(key: K, value: TConfig[K], source?: TConfigSource): void` | Set a value. Target is `'OVERRIDE'` by default. |
|
|
88
|
+
| `Validate` | `Validate<K>(key: K, value: unknown): boolean` | Check whether a value satisfies the field schema without setting it. |
|
|
89
|
+
| `IsSecret` | `IsSecret(key: TKeys): boolean` | Returns `true` if the field was wrapped with `Secret()`. |
|
|
90
|
+
| `GetSecretKeys` | `GetSecretKeys(): Array<TKeys>` | Returns all keys marked with `Secret()` in schema insertion order. |
|
|
91
|
+
| `Redact` | `Redact(): Record<string, unknown>` | Returns all resolved values; secret fields are replaced with `'***'`. Unset/unregistered keys are omitted. |
|
|
92
|
+
|
|
93
|
+
**Important:** Call `ConfigManager.RegisterProvider` for all providers before any module that calls `RegisterConfigSchema` is imported. Provider values are captured when schemas are registered.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### `Secret(schema)`
|
|
98
|
+
|
|
99
|
+
Marks a Zod field schema as secret using Zod v4's `globalRegistry` metadata. The TypeScript inferred type of the schema is unchanged.
|
|
37
100
|
|
|
38
101
|
```typescript
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
102
|
+
function Secret<T extends z.ZodTypeAny>(schema: T): T
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { Secret } from '@pawells/config';
|
|
107
|
+
import { z } from 'zod';
|
|
108
|
+
|
|
109
|
+
// In a schema definition:
|
|
110
|
+
const schema = z.object({
|
|
111
|
+
API_KEY: Secret(z.string().min(32)).default(''),
|
|
49
112
|
});
|
|
113
|
+
```
|
|
50
114
|
|
|
51
|
-
|
|
52
|
-
|
|
115
|
+
Secret fields are:
|
|
116
|
+
- Blanked (empty value) in `.env` template output (`ConfigEnvironmentProvider.Save` in template mode).
|
|
117
|
+
- Written as `null` in JSON template output (`ConfigJSONProvider.Save` in template mode).
|
|
118
|
+
- Replaced with `'***'` by `IConfigSchemaObject.Redact()`.
|
|
119
|
+
- Sanitized from `ConfigValidationError` messages and causes on validation failure.
|
|
53
120
|
|
|
54
|
-
|
|
55
|
-
ServiceConfig.Register();
|
|
121
|
+
---
|
|
56
122
|
|
|
57
|
-
|
|
58
|
-
ServiceConfig.ParseENV();
|
|
123
|
+
### `ConfigManager`
|
|
59
124
|
|
|
60
|
-
|
|
61
|
-
const port = ServiceConfig.Get('PORT'); // number, typed
|
|
62
|
-
const host = ServiceConfig.Get('HOST'); // string, typed
|
|
63
|
-
const debug = ServiceConfig.Get('DEBUG'); // boolean, typed
|
|
125
|
+
A static singleton configuration manager. All state is shared across the process for the lifetime of the module.
|
|
64
126
|
|
|
65
|
-
|
|
127
|
+
```typescript
|
|
128
|
+
class ConfigManager {
|
|
129
|
+
static Register(key: string, schema: z.ZodTypeAny, defaultValue: unknown): void
|
|
130
|
+
static Get(key: string, source?: TConfigSource): TConfigValueTypes
|
|
131
|
+
static Set<T extends TConfigValueTypes>(key: string, value: T, target?: TConfigSource): void
|
|
132
|
+
static GetSchema(key: string): z.ZodTypeAny
|
|
133
|
+
static async RegisterProvider(provider: IConfigProvider): Promise<void>
|
|
134
|
+
static RegisterSyncProvider(provider: ISyncConfigProvider): void
|
|
135
|
+
static async Save(provider: IConfigProvider, options: SaveOptions): Promise<void>
|
|
136
|
+
static RegisterNamespace(name: string, prefix: string): void
|
|
137
|
+
static SetValidationWarningHandler(handler: ((key: string, providerName: string) => void) | undefined): void
|
|
138
|
+
static Reset(): void
|
|
139
|
+
}
|
|
66
140
|
```
|
|
67
141
|
|
|
68
|
-
|
|
142
|
+
| Method | Description |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `Register(key, schema, defaultValue)` | Register a key with its Zod schema and initial default. Throws `ConfigRegistrationError` if re-registered with a different schema. Throws `ConfigValidationError` if `defaultValue` fails. |
|
|
145
|
+
| `Get(key, source?)` | Retrieve the resolved value for `key`. Pass `'DEFAULT'` or `'OVERRIDE'` to read a specific tier only. Throws `ConfigNotRegisteredError` or `ConfigNotSetError` if unavailable. |
|
|
146
|
+
| `Set(key, value, target?)` | Set a value on the `'OVERRIDE'` tier (default) or `'DEFAULT'` tier. Throws `ConfigNotRegisteredError` or `ConfigValidationError`. |
|
|
147
|
+
| `GetSchema(key)` | Return the registered Zod schema for `key`. Throws `ConfigNotRegisteredError`. |
|
|
148
|
+
| `RegisterProvider(provider)` | Async. Register an `IConfigProvider`; calls `provider.Load()` immediately. Provider values are the middle tier. Last-registered wins for duplicate keys. |
|
|
149
|
+
| `RegisterSyncProvider(provider)` | Register an `ISyncConfigProvider`; calls `provider.LoadSync()` immediately. Use only when `await` is not available. |
|
|
150
|
+
| `Save(provider, options)` | Async. Build a `ConfigSaveEntry[]` for every registered key and delegate to `provider.Save()`. |
|
|
151
|
+
| `RegisterNamespace(name, prefix)` | Record a `prefix → sectionName` mapping used by `Save()` to split keys into section/field components. Called automatically by `RegisterConfigSchema`. |
|
|
152
|
+
| `SetValidationWarningHandler(handler)` | Set a callback invoked when a provider value fails schema validation. Silent by default. Pass `undefined` to clear. |
|
|
153
|
+
| `Reset()` | Clear all state. Intended for test isolation only. |
|
|
69
154
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
155
|
+
**`TConfigSource`** — `'DEFAULT' | 'OVERRIDE'`
|
|
156
|
+
|
|
157
|
+
**`TConfigValueTypes`** — the full union accepted by all schemas:
|
|
158
|
+
`string | number | boolean | Date | string[] | number[] | boolean[] | undefined | null`
|
|
73
159
|
|
|
74
|
-
|
|
75
|
-
const isValid = ServiceConfig.Validate('PORT', '8080'); // true if valid
|
|
160
|
+
**`TConfig`** — `Map<string, TConfigValueTypes>`
|
|
76
161
|
|
|
77
|
-
|
|
78
|
-
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### `ScopedConfigManager`
|
|
165
|
+
|
|
166
|
+
An instance-based configuration manager. Each instance maintains fully independent state, making it suitable for test isolation and multi-tenant scenarios. The public API mirrors `ConfigManager` exactly as instance methods.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const config = new ScopedConfigManager();
|
|
170
|
+
config.Register('PORT', z.coerce.number(), 3000);
|
|
171
|
+
await config.RegisterProvider(myProvider);
|
|
172
|
+
const port = config.Get('PORT'); // 3000
|
|
79
173
|
```
|
|
80
174
|
|
|
81
|
-
|
|
175
|
+
`ScopedConfigManager` exposes: `Register`, `Get`, `Set`, `GetSchema`, `RegisterProvider`, `RegisterSyncProvider`, `Save`, `RegisterNamespace`, `SetValidationWarningHandler`, `Reset`.
|
|
82
176
|
|
|
83
|
-
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### `ConfigProvider` (abstract base class)
|
|
180
|
+
|
|
181
|
+
Extend this class to build a custom provider. Both `Load` and `Save` are abstract and must be implemented.
|
|
84
182
|
|
|
85
183
|
```typescript
|
|
86
|
-
|
|
87
|
-
|
|
184
|
+
abstract class ConfigProvider<
|
|
185
|
+
TOptions extends TConfigProviderOptions = TConfigProviderOptions,
|
|
186
|
+
TLoadOptions = unknown,
|
|
187
|
+
TSaveOptions extends TConfigProviderSaveOptions = TConfigProviderSaveOptions
|
|
188
|
+
> {
|
|
189
|
+
readonly Name: string
|
|
190
|
+
abstract Load(options?: TLoadOptions): Promise<Record<string, unknown>>
|
|
191
|
+
abstract Save(entries: readonly ConfigSaveEntry[], options?: TSaveOptions): Promise<void>
|
|
192
|
+
}
|
|
193
|
+
```
|
|
88
194
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
ConfigManager.Register('API_KEY', z.string().min(32), 'default-key');
|
|
195
|
+
```typescript
|
|
196
|
+
import { ConfigProvider, type TConfigProviderOptions, type ConfigSaveEntry } from '@pawells/config';
|
|
92
197
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
198
|
+
class RedisProvider extends ConfigProvider {
|
|
199
|
+
async Load(): Promise<Record<string, unknown>> {
|
|
200
|
+
// Return a flat key-value record; keys must be fully qualified.
|
|
201
|
+
return { APP_HOST: 'redis-host' };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async Save(_entries: readonly ConfigSaveEntry[]): Promise<void> {
|
|
205
|
+
// Implement if this provider supports writes.
|
|
206
|
+
}
|
|
207
|
+
}
|
|
96
208
|
```
|
|
97
209
|
|
|
98
|
-
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Provider interfaces
|
|
213
|
+
|
|
214
|
+
**`IConfigProvider`** — async providers (preferred):
|
|
99
215
|
|
|
100
216
|
```typescript
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
217
|
+
interface IConfigProvider {
|
|
218
|
+
readonly Name: string
|
|
219
|
+
Load(): Promise<Record<string, unknown>>
|
|
220
|
+
Save(entries: readonly ConfigSaveEntry[], options?: SaveOptions): Promise<void>
|
|
221
|
+
}
|
|
222
|
+
```
|
|
106
223
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
if (error instanceof ConfigurationNotSetError) {
|
|
115
|
-
console.error('Configuration value not set:', error.message);
|
|
116
|
-
}
|
|
117
|
-
if (error instanceof ConfigurationError) {
|
|
118
|
-
console.error('Validation failed:', error.message);
|
|
119
|
-
}
|
|
224
|
+
**`ISyncConfigProvider`** — synchronous read-only providers (escape hatch):
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
interface ISyncConfigProvider {
|
|
228
|
+
readonly Name: string
|
|
229
|
+
LoadSync(): Record<string, unknown>
|
|
120
230
|
}
|
|
121
231
|
```
|
|
122
232
|
|
|
123
|
-
|
|
233
|
+
---
|
|
124
234
|
|
|
125
|
-
###
|
|
235
|
+
### `SaveOptions`
|
|
126
236
|
|
|
127
|
-
|
|
237
|
+
Passed to `ConfigManager.Save` and `IConfigProvider.Save`:
|
|
128
238
|
|
|
129
|
-
**Signature:**
|
|
130
239
|
```typescript
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
240
|
+
interface SaveOptions {
|
|
241
|
+
path: string // Destination file path
|
|
242
|
+
useCurrentValues?: boolean // false (default) = registered defaults; true = live resolved values
|
|
243
|
+
}
|
|
135
244
|
```
|
|
136
245
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
|
148
|
-
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
> // ✓ Good: Load from environment at startup
|
|
199
|
-
> ConfigManager.Set('DATABASE_PASSWORD', process.env.DB_PASSWORD);
|
|
200
|
-
>
|
|
201
|
-
> // ✗ Bad: Hardcoded secrets
|
|
202
|
-
> ConfigManager.Register('DATABASE_PASSWORD', z.string(), 'hardcoded-password');
|
|
203
|
-
> ```
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### `ConfigSaveEntry` / `IConfigSaveEntry`
|
|
249
|
+
|
|
250
|
+
One entry per registered key, built by `ConfigManager.Save` and passed to `provider.Save`:
|
|
251
|
+
|
|
252
|
+
| Field | Type | Description |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| `key` | `string` | Fully-qualified key (e.g. `DATABASE_HOST`) |
|
|
255
|
+
| `section` | `string` | Namespace section (e.g. `DATABASE`); empty string if no namespace |
|
|
256
|
+
| `field` | `string` | Field within the section (e.g. `HOST`); equals `key` when section is empty |
|
|
257
|
+
| `value` | `unknown` | Default or live value, depending on `useCurrentValues` |
|
|
258
|
+
| `isSecret` | `boolean` | `true` if the field was wrapped with `Secret()` |
|
|
259
|
+
| `description` | `string \| undefined` | From Zod `.describe()` annotation |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Error classes
|
|
264
|
+
|
|
265
|
+
All errors extend `ConfigError`, which in turn extends `BaseError` from `@pawells/typescript-common`.
|
|
266
|
+
|
|
267
|
+
| Class | Error code | Thrown when |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| `ConfigError` | `CONFIG_ERROR` | General configuration error; base class for all others |
|
|
270
|
+
| `ConfigRegistrationError` | `CONFIG_REGISTRATION_ERROR` | A key is registered a second time with a different schema |
|
|
271
|
+
| `ConfigNotSetError` | `CONFIG_NOT_SET_ERROR` | `Get()` is called for a key with no value in the requested tier |
|
|
272
|
+
| `ConfigNotRegisteredError` | `CONFIG_NOT_REGISTERED` | `Get()`, `Set()`, or `GetSchema()` is called for an unregistered key |
|
|
273
|
+
| `ConfigValidationError` | `CONFIG_VALIDATION_ERROR` | A value fails its Zod schema at `Register()`, `Set()`, or `Get()` time |
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import { ConfigError, ConfigNotRegisteredError, ConfigNotSetError, ConfigValidationError } from '@pawells/config';
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
const value = ConfigManager.Get('MISSING_KEY');
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (error instanceof ConfigNotRegisteredError) {
|
|
282
|
+
// Key was never registered
|
|
283
|
+
} else if (error instanceof ConfigNotSetError) {
|
|
284
|
+
// Key is registered but has no value in the requested tier
|
|
285
|
+
} else if (error instanceof ConfigValidationError) {
|
|
286
|
+
// Value failed schema validation; check error.cause for Zod details
|
|
287
|
+
} else if (error instanceof ConfigError) {
|
|
288
|
+
// Any other configuration error
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### Schema constants and utilities
|
|
296
|
+
|
|
297
|
+
| Export | Description |
|
|
298
|
+
|---|---|
|
|
299
|
+
| `CONFIG_VALUES_TYPES_SCHEMA` | Zod union schema accepting all supported config value types |
|
|
300
|
+
| `AssertConfigValueType(value)` | Asserts that `value` is a `TConfigValueTypes`; throws `ZodError` otherwise |
|
|
301
|
+
| `CONFIG_PROVIDER_OPTIONS_SCHEMA` | Zod schema for `{ name: string }` base provider options |
|
|
302
|
+
| `TConfigProviderOptions` | Inferred type of `CONFIG_PROVIDER_OPTIONS_SCHEMA` |
|
|
303
|
+
| `AssertConfigProviderOptions(options)` | Asserts conformance; throws `ZodError` otherwise |
|
|
304
|
+
| `ValidateConfigProviderOptions(options)` | Returns `true` if options conform; `false` otherwise |
|
|
305
|
+
| `CONFIG_PROVIDER_SAVE_OPTIONS_SCHEMA` | Zod schema for `{ useCurrentValues?: boolean }` |
|
|
306
|
+
| `TConfigProviderSaveOptions` | Inferred type of `CONFIG_PROVIDER_SAVE_OPTIONS_SCHEMA` |
|
|
204
307
|
|
|
205
308
|
## License
|
|
206
309
|
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Custom error classes for configuration management.
|
|
3
3
|
*
|
|
4
|
-
* Exports: {@link
|
|
5
|
-
* {@link
|
|
4
|
+
* Exports: {@link ConfigRegistrationError}, {@link ConfigNotRegisteredError},
|
|
5
|
+
* {@link ConfigError}, and {@link ConfigNotSetError}.
|
|
6
6
|
*/
|
|
7
|
+
import { BaseError, type TErrorMetadata } from '@pawells/typescript-common';
|
|
7
8
|
/**
|
|
8
9
|
* Abstract base class for configuration errors.
|
|
9
10
|
* Automatically sets the error name to the class constructor name.
|
|
10
11
|
*/
|
|
11
|
-
declare
|
|
12
|
-
|
|
13
|
-
constructor(message: string);
|
|
12
|
+
export declare class ConfigError extends BaseError {
|
|
13
|
+
constructor(message: string, metadata?: TErrorMetadata);
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Error thrown when attempting to register a configuration key that already exists.
|
|
@@ -18,51 +18,43 @@ declare abstract class ConfigurationBaseError extends Error {
|
|
|
18
18
|
* @param key - The configuration key that was already registered
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
|
-
* throw new
|
|
21
|
+
* throw new ConfigRegistrationError('DATABASE_URL');
|
|
22
22
|
*/
|
|
23
|
-
export declare class
|
|
24
|
-
|
|
25
|
-
constructor(key: string);
|
|
23
|
+
export declare class ConfigRegistrationError extends ConfigError {
|
|
24
|
+
constructor(key: string, metadata?: TErrorMetadata);
|
|
26
25
|
}
|
|
27
26
|
/**
|
|
28
|
-
* Error thrown when
|
|
27
|
+
* Error thrown when a required configuration value is not set.
|
|
29
28
|
*
|
|
30
|
-
* @param key - The configuration key that is not
|
|
29
|
+
* @param key - The configuration key that is not set
|
|
31
30
|
*
|
|
32
31
|
* @example
|
|
33
|
-
* throw new
|
|
32
|
+
* throw new ConfigNotSetError('DATABASE_URL');
|
|
34
33
|
*/
|
|
35
|
-
export declare class
|
|
36
|
-
|
|
37
|
-
constructor(key: string);
|
|
34
|
+
export declare class ConfigNotSetError extends ConfigError {
|
|
35
|
+
constructor(key: string, metadata?: TErrorMetadata);
|
|
38
36
|
}
|
|
39
37
|
/**
|
|
40
|
-
* Error thrown when configuration
|
|
38
|
+
* Error thrown when a configuration key is not registered.
|
|
41
39
|
*
|
|
42
|
-
* @param key - The configuration key that
|
|
43
|
-
* @param message - Detailed error message about the validation failure
|
|
44
|
-
* @param options - Optional options object with cause
|
|
40
|
+
* @param key - The configuration key that is not registered
|
|
45
41
|
*
|
|
46
42
|
* @example
|
|
47
|
-
* throw new
|
|
43
|
+
* throw new ConfigNotRegisteredError('DATABASE_URL');
|
|
48
44
|
*/
|
|
49
|
-
export declare class
|
|
50
|
-
|
|
51
|
-
constructor(key: string, message: string, options?: {
|
|
52
|
-
cause?: Error;
|
|
53
|
-
});
|
|
45
|
+
export declare class ConfigNotRegisteredError extends ConfigError {
|
|
46
|
+
constructor(key: string, metadata?: TErrorMetadata);
|
|
54
47
|
}
|
|
55
48
|
/**
|
|
56
|
-
* Error thrown when a
|
|
49
|
+
* Error thrown when a configuration value fails schema validation.
|
|
57
50
|
*
|
|
58
|
-
* @param key - The configuration key that
|
|
51
|
+
* @param key - The configuration key that failed validation
|
|
52
|
+
* @param validationMessage - The validation error message describing why the value is invalid
|
|
59
53
|
*
|
|
60
54
|
* @example
|
|
61
|
-
* throw new
|
|
55
|
+
* throw new ConfigValidationError('PORT', 'Expected a number between 1 and 65535');
|
|
62
56
|
*/
|
|
63
|
-
export declare class
|
|
64
|
-
|
|
65
|
-
constructor(key: string);
|
|
57
|
+
export declare class ConfigValidationError extends ConfigError {
|
|
58
|
+
constructor(key: string, validationMessage: string, metadata?: TErrorMetadata);
|
|
66
59
|
}
|
|
67
|
-
export {};
|
|
68
60
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5E;;;GAGG;AACH,qBAAa,WAAY,SAAQ,SAAS;gBAC7B,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB;CAI1D;AAED;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,WAAW;gBAC3C,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB;CAItD;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;gBACrC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB;CAItD;AAED;;;;;;;GAOG;AACH,qBAAa,wBAAyB,SAAQ,WAAW;gBAC5C,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB;CAItD;AAED;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,WAAW;gBACzC,GAAG,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB;CAIjF"}
|