@outfitter/config 0.3.3 → 0.4.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 +28 -23
- package/dist/index.d.ts +6 -506
- package/dist/index.js +33 -309
- package/dist/internal/extends.d.ts +13 -0
- package/dist/internal/extends.js +10 -0
- package/dist/internal/loading.d.ts +3 -0
- package/dist/internal/loading.js +9 -0
- package/dist/internal/parsing.d.ts +2 -0
- package/dist/internal/parsing.js +13 -0
- package/dist/internal/xdg.d.ts +2 -0
- package/dist/internal/xdg.js +13 -0
- package/dist/shared/@outfitter/config-6449x3br.d.ts +81 -0
- package/dist/shared/@outfitter/config-7dyshh4r.d.ts +105 -0
- package/dist/shared/@outfitter/config-aje2en96.js +71 -0
- package/dist/shared/@outfitter/config-br341dr7.js +87 -0
- package/dist/shared/@outfitter/config-pf9xp78h.js +29 -0
- package/dist/shared/@outfitter/config-s4swz8m3.js +97 -0
- package/dist/shared/@outfitter/config-sp6gradd.d.ts +129 -0
- package/package.json +25 -25
package/README.md
CHANGED
|
@@ -59,11 +59,13 @@ if (result.isOk()) {
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
**Parameters:**
|
|
62
|
+
|
|
62
63
|
- `appName` - Application name for XDG directory lookup
|
|
63
64
|
- `schema` - Zod schema for validation
|
|
64
65
|
- `options.searchPaths` - Custom search paths (overrides XDG defaults)
|
|
65
66
|
|
|
66
67
|
**Search Order:**
|
|
68
|
+
|
|
67
69
|
1. Custom `searchPaths` if provided
|
|
68
70
|
2. `$XDG_CONFIG_HOME/{appName}/config.{ext}`
|
|
69
71
|
3. `~/.config/{appName}/config.{ext}`
|
|
@@ -88,6 +90,7 @@ const result = resolveConfig(AppSchema, {
|
|
|
88
90
|
```
|
|
89
91
|
|
|
90
92
|
**Parameters:**
|
|
93
|
+
|
|
91
94
|
- `schema` - Zod schema for validation
|
|
92
95
|
- `sources` - Configuration sources to merge
|
|
93
96
|
|
|
@@ -113,6 +116,7 @@ if (result.isOk()) {
|
|
|
113
116
|
```
|
|
114
117
|
|
|
115
118
|
**Parameters:**
|
|
119
|
+
|
|
116
120
|
- `content` - Raw file content
|
|
117
121
|
- `filename` - Filename (extension determines parser)
|
|
118
122
|
|
|
@@ -179,6 +183,7 @@ const merged = deepMerge(defaults, overrides);
|
|
|
179
183
|
```
|
|
180
184
|
|
|
181
185
|
**Merge Behavior:**
|
|
186
|
+
|
|
182
187
|
- Recursively merges nested plain objects
|
|
183
188
|
- Arrays are replaced (not concatenated)
|
|
184
189
|
- `null` explicitly replaces the target value
|
|
@@ -194,10 +199,10 @@ Configuration sources for multi-layer resolution.
|
|
|
194
199
|
|
|
195
200
|
```typescript
|
|
196
201
|
interface ConfigSources<T> {
|
|
197
|
-
defaults?: Partial<T>;
|
|
198
|
-
file?: Partial<T>;
|
|
199
|
-
env?: Partial<T>;
|
|
200
|
-
flags?: Partial<T>;
|
|
202
|
+
defaults?: Partial<T>; // Lowest precedence
|
|
203
|
+
file?: Partial<T>; // From config file
|
|
204
|
+
env?: Partial<T>; // Environment variables
|
|
205
|
+
flags?: Partial<T>; // CLI flags (highest)
|
|
201
206
|
}
|
|
202
207
|
```
|
|
203
208
|
|
|
@@ -207,7 +212,7 @@ Options for `loadConfig()`.
|
|
|
207
212
|
|
|
208
213
|
```typescript
|
|
209
214
|
interface LoadConfigOptions {
|
|
210
|
-
searchPaths?: string[];
|
|
215
|
+
searchPaths?: string[]; // Custom search paths
|
|
211
216
|
}
|
|
212
217
|
```
|
|
213
218
|
|
|
@@ -256,11 +261,11 @@ const prodDefaults = getEnvironmentDefaults("production");
|
|
|
256
261
|
// { logLevel: null, verbose: false, errorDetail: "message" }
|
|
257
262
|
```
|
|
258
263
|
|
|
259
|
-
| Setting
|
|
260
|
-
|
|
261
|
-
| logLevel
|
|
262
|
-
| verbose
|
|
263
|
-
| errorDetail | `"full"`
|
|
264
|
+
| Setting | `development` | `production` | `test` |
|
|
265
|
+
| ----------- | ------------- | ------------ | -------- |
|
|
266
|
+
| logLevel | `"debug"` | `null` | `null` |
|
|
267
|
+
| verbose | `true` | `false` | `false` |
|
|
268
|
+
| errorDetail | `"full"` | `"message"` | `"full"` |
|
|
264
269
|
|
|
265
270
|
### Types
|
|
266
271
|
|
|
@@ -286,12 +291,12 @@ interface EnvironmentDefaults {
|
|
|
286
291
|
|
|
287
292
|
This package follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) for locating configuration files.
|
|
288
293
|
|
|
289
|
-
| Variable
|
|
290
|
-
|
|
291
|
-
| `XDG_CONFIG_HOME` | `~/.config`
|
|
292
|
-
| `XDG_DATA_HOME`
|
|
293
|
-
| `XDG_CACHE_HOME`
|
|
294
|
-
| `XDG_STATE_HOME`
|
|
294
|
+
| Variable | macOS/Linux Default | Purpose |
|
|
295
|
+
| ----------------- | ------------------- | -------------------------------- |
|
|
296
|
+
| `XDG_CONFIG_HOME` | `~/.config` | User-specific configuration |
|
|
297
|
+
| `XDG_DATA_HOME` | `~/.local/share` | User-specific data files |
|
|
298
|
+
| `XDG_CACHE_HOME` | `~/.cache` | Non-essential cached data |
|
|
299
|
+
| `XDG_STATE_HOME` | `~/.local/state` | Persistent state (logs, history) |
|
|
295
300
|
|
|
296
301
|
---
|
|
297
302
|
|
|
@@ -317,13 +322,13 @@ Higher precedence sources override lower ones. Nested objects are deep-merged.
|
|
|
317
322
|
|
|
318
323
|
## Supported File Formats
|
|
319
324
|
|
|
320
|
-
| Extension
|
|
321
|
-
|
|
322
|
-
| `.toml`
|
|
323
|
-
| `.yaml`, `.yml` | yaml
|
|
324
|
-
| `.json`
|
|
325
|
-
| `.jsonc`
|
|
326
|
-
| `.json5`
|
|
325
|
+
| Extension | Parser | Notes |
|
|
326
|
+
| --------------- | ---------- | -------------------------------------- |
|
|
327
|
+
| `.toml` | smol-toml | Preferred for configuration |
|
|
328
|
+
| `.yaml`, `.yml` | yaml | YAML anchors/aliases supported |
|
|
329
|
+
| `.json` | JSON.parse | Strict parsing |
|
|
330
|
+
| `.jsonc` | json5 | JSON with comments and trailing commas |
|
|
331
|
+
| `.json5` | json5 | Comments and trailing commas allowed |
|
|
327
332
|
|
|
328
333
|
---
|
|
329
334
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,443 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* `"production"` when unset or invalid.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { getEnvironment, getEnvironmentDefaults } from "@outfitter/config";
|
|
12
|
-
*
|
|
13
|
-
* const env = getEnvironment(); // "development" | "production" | "test"
|
|
14
|
-
* const defaults = getEnvironmentDefaults(env);
|
|
15
|
-
*
|
|
16
|
-
* if (defaults.verbose) {
|
|
17
|
-
* console.log("Verbose mode enabled");
|
|
18
|
-
* }
|
|
19
|
-
* ```
|
|
20
|
-
*
|
|
21
|
-
* @module
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* Valid Outfitter environment names.
|
|
25
|
-
*
|
|
26
|
-
* - `"development"` — Local development with verbose output and debug logging
|
|
27
|
-
* - `"production"` — Production deployments with minimal output
|
|
28
|
-
* - `"test"` — Test runs with full error detail but no logging
|
|
29
|
-
*/
|
|
30
|
-
type OutfitterEnv = "development" | "production" | "test";
|
|
31
|
-
/**
|
|
32
|
-
* Profile-specific defaults for an environment.
|
|
33
|
-
*
|
|
34
|
-
* These defaults provide sensible starting values that individual
|
|
35
|
-
* packages can override or extend.
|
|
36
|
-
*/
|
|
37
|
-
interface EnvironmentDefaults {
|
|
38
|
-
/** How much error detail to include in output. */
|
|
39
|
-
errorDetail: "full" | "message";
|
|
40
|
-
/** Default log level. `null` means logging is disabled by default. */
|
|
41
|
-
logLevel: "debug" | "info" | "warn" | "error" | null;
|
|
42
|
-
/** Whether verbose output is enabled by default. */
|
|
43
|
-
verbose: boolean;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Determine the current Outfitter environment.
|
|
47
|
-
*
|
|
48
|
-
* Reads the `OUTFITTER_ENV` environment variable. If set to a valid
|
|
49
|
-
* value (`"development"`, `"production"`, or `"test"`), returns that
|
|
50
|
-
* value. Otherwise falls back to `"production"`.
|
|
51
|
-
*
|
|
52
|
-
* @returns The current environment
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```typescript
|
|
56
|
-
* // With OUTFITTER_ENV=development
|
|
57
|
-
* getEnvironment(); // "development"
|
|
58
|
-
*
|
|
59
|
-
* // With OUTFITTER_ENV unset or invalid
|
|
60
|
-
* getEnvironment(); // "production"
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
declare function getEnvironment(): OutfitterEnv;
|
|
64
|
-
/**
|
|
65
|
-
* Get the default settings for an environment profile.
|
|
66
|
-
*
|
|
67
|
-
* Returns a shallow copy of the defaults for the given environment.
|
|
68
|
-
* These defaults are intended as starting values that individual
|
|
69
|
-
* packages can override via their own configuration.
|
|
70
|
-
*
|
|
71
|
-
* | Setting | `development` | `production` | `test` |
|
|
72
|
-
* |---------|--------------|-------------|--------|
|
|
73
|
-
* | logLevel | `"debug"` | `null` | `null` |
|
|
74
|
-
* | verbose | `true` | `false` | `false` |
|
|
75
|
-
* | errorDetail | `"full"` | `"message"` | `"full"` |
|
|
76
|
-
*
|
|
77
|
-
* @param env - The environment to get defaults for
|
|
78
|
-
* @returns Profile-specific default settings
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```typescript
|
|
82
|
-
* const defaults = getEnvironmentDefaults("development");
|
|
83
|
-
* // { logLevel: "debug", verbose: true, errorDetail: "full" }
|
|
84
|
-
*
|
|
85
|
-
* const prodDefaults = getEnvironmentDefaults("production");
|
|
86
|
-
* // { logLevel: null, verbose: false, errorDetail: "message" }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
declare function getEnvironmentDefaults(env: OutfitterEnv): EnvironmentDefaults;
|
|
90
|
-
import { z } from "zod";
|
|
91
|
-
/**
|
|
92
|
-
* Port number schema (1-65535) with string-to-number coercion.
|
|
93
|
-
*
|
|
94
|
-
* Validates that a string contains only digits, then transforms
|
|
95
|
-
* to a number and validates the port range.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```typescript
|
|
99
|
-
* const schema = z.object({ PORT: portSchema });
|
|
100
|
-
* schema.parse({ PORT: "3000" }); // { PORT: 3000 }
|
|
101
|
-
* schema.parse({ PORT: "invalid" }); // throws
|
|
102
|
-
* schema.parse({ PORT: "99999" }); // throws (out of range)
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
declare const portSchema: z.ZodType<number, string>;
|
|
106
|
-
/**
|
|
107
|
-
* Boolean schema with proper string coercion.
|
|
108
|
-
*
|
|
109
|
-
* Accepts: "true", "false", "1", "0", ""
|
|
110
|
-
* - "true" or "1" -> true
|
|
111
|
-
* - "false", "0", or "" -> false
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```typescript
|
|
115
|
-
* const schema = z.object({ DEBUG: booleanSchema });
|
|
116
|
-
* schema.parse({ DEBUG: "true" }); // { DEBUG: true }
|
|
117
|
-
* schema.parse({ DEBUG: "1" }); // { DEBUG: true }
|
|
118
|
-
* schema.parse({ DEBUG: "false" }); // { DEBUG: false }
|
|
119
|
-
* schema.parse({ DEBUG: "" }); // { DEBUG: false }
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
declare const booleanSchema: z.ZodType<boolean, string>;
|
|
123
|
-
/**
|
|
124
|
-
* Optional boolean schema - returns undefined if not set.
|
|
125
|
-
*
|
|
126
|
-
* Unlike `booleanSchema`, this returns `undefined` for missing
|
|
127
|
-
* or empty values, allowing callers to distinguish between
|
|
128
|
-
* "explicitly set to false" and "not set".
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* ```typescript
|
|
132
|
-
* const schema = z.object({ NO_COLOR: optionalBooleanSchema });
|
|
133
|
-
* schema.parse({ NO_COLOR: "true" }); // { NO_COLOR: true }
|
|
134
|
-
* schema.parse({ NO_COLOR: "" }); // { NO_COLOR: undefined }
|
|
135
|
-
* schema.parse({ NO_COLOR: undefined }); // { NO_COLOR: undefined }
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
declare const optionalBooleanSchema: z.ZodType<boolean | undefined, string | undefined>;
|
|
139
|
-
/**
|
|
140
|
-
* Parse and validate environment variables against a Zod schema.
|
|
141
|
-
*
|
|
142
|
-
* By default reads from `process.env`, but accepts a custom env
|
|
143
|
-
* object for testing.
|
|
144
|
-
*
|
|
145
|
-
* @typeParam T - The Zod schema shape
|
|
146
|
-
* @param schema - Zod object schema to validate against
|
|
147
|
-
* @param envObj - Environment object (defaults to process.env)
|
|
148
|
-
* @returns Validated and transformed environment object
|
|
149
|
-
* @throws {z.ZodError} When validation fails
|
|
150
|
-
*
|
|
151
|
-
* @example
|
|
152
|
-
* ```typescript
|
|
153
|
-
* const AppEnv = z.object({
|
|
154
|
-
* PORT: portSchema,
|
|
155
|
-
* DEBUG: booleanSchema,
|
|
156
|
-
* });
|
|
157
|
-
*
|
|
158
|
-
* const env = parseEnv(AppEnv);
|
|
159
|
-
* console.log(env.PORT); // number
|
|
160
|
-
* console.log(env.DEBUG); // boolean
|
|
161
|
-
* ```
|
|
162
|
-
*/
|
|
163
|
-
declare function parseEnv<T extends z.ZodRawShape>(schema: z.ZodObject<T>, envObj?: Record<string, string | undefined>): z.infer<z.ZodObject<T>>;
|
|
164
|
-
type AppEnvShape = {
|
|
165
|
-
NODE_ENV: z.ZodDefault<z.ZodEnum<{
|
|
166
|
-
development: "development";
|
|
167
|
-
test: "test";
|
|
168
|
-
production: "production";
|
|
169
|
-
}>>;
|
|
170
|
-
NO_COLOR: typeof optionalBooleanSchema;
|
|
171
|
-
FORCE_COLOR: typeof optionalBooleanSchema;
|
|
172
|
-
CI: typeof optionalBooleanSchema;
|
|
173
|
-
TERM: z.ZodOptional<z.ZodString>;
|
|
174
|
-
XDG_CONFIG_HOME: z.ZodOptional<z.ZodString>;
|
|
175
|
-
XDG_DATA_HOME: z.ZodOptional<z.ZodString>;
|
|
176
|
-
XDG_STATE_HOME: z.ZodOptional<z.ZodString>;
|
|
177
|
-
XDG_CACHE_HOME: z.ZodOptional<z.ZodString>;
|
|
178
|
-
HOME: z.ZodOptional<z.ZodString>;
|
|
179
|
-
};
|
|
180
|
-
/**
|
|
181
|
-
* Schema for common application environment variables.
|
|
182
|
-
*/
|
|
183
|
-
declare const appEnvSchema: z.ZodObject<AppEnvShape>;
|
|
184
|
-
/**
|
|
185
|
-
* Type for the pre-parsed application environment.
|
|
186
|
-
*/
|
|
187
|
-
type Env = z.infer<typeof appEnvSchema>;
|
|
188
|
-
/**
|
|
189
|
-
* Pre-parsed application environment.
|
|
190
|
-
*
|
|
191
|
-
* Access common environment variables with proper typing:
|
|
192
|
-
* - `env.NODE_ENV`: "development" | "test" | "production"
|
|
193
|
-
* - `env.NO_COLOR`: boolean | undefined
|
|
194
|
-
* - `env.FORCE_COLOR`: boolean | undefined
|
|
195
|
-
* - `env.CI`: boolean | undefined
|
|
196
|
-
* - `env.TERM`: string | undefined
|
|
197
|
-
* - `env.XDG_*`: string | undefined
|
|
198
|
-
* - `env.HOME`: string | undefined
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* import { env } from "@outfitter/config";
|
|
203
|
-
*
|
|
204
|
-
* if (env.CI) {
|
|
205
|
-
* console.log("Running in CI environment");
|
|
206
|
-
* }
|
|
207
|
-
*
|
|
208
|
-
* if (env.NO_COLOR) {
|
|
209
|
-
* // Disable color output
|
|
210
|
-
* }
|
|
211
|
-
* ```
|
|
212
|
-
*/
|
|
213
|
-
declare const env: Env;
|
|
214
|
-
/**
|
|
215
|
-
* Reads an optional boolean from process.env at call time.
|
|
216
|
-
*
|
|
217
|
-
* Unlike `env.NO_COLOR` (which is static), this reads dynamically
|
|
218
|
-
* for use cases where env vars may change at runtime (e.g., tests).
|
|
219
|
-
*
|
|
220
|
-
* @param key - The environment variable name to read
|
|
221
|
-
* @returns `true` if "true"/"1", `false` if "false"/"0", `undefined` otherwise
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* // For terminal detection that needs dynamic behavior
|
|
226
|
-
* if (getEnvBoolean("NO_COLOR")) {
|
|
227
|
-
* // colors disabled
|
|
228
|
-
* }
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
declare function getEnvBoolean(key: "NO_COLOR" | "FORCE_COLOR" | "CI"): boolean | undefined;
|
|
232
|
-
import { TaggedErrorClass } from "@outfitter/contracts";
|
|
233
|
-
import { NotFoundError, Result, ValidationError } from "@outfitter/contracts";
|
|
1
|
+
import { Env, booleanSchema, env, getEnvBoolean, optionalBooleanSchema, parseEnv, portSchema } from "./shared/@outfitter/config-veqxf02x.js";
|
|
2
|
+
import { EnvironmentDefaults, OutfitterEnv, getEnvironment, getEnvironmentDefaults } from "./shared/@outfitter/config-wawavx3r.js";
|
|
3
|
+
import { getCacheDir, getConfigDir, getDataDir, getStateDir } from "./shared/@outfitter/config-6449x3br.js";
|
|
4
|
+
import { LoadConfigOptions, loadConfig } from "./shared/@outfitter/config-7dyshh4r.js";
|
|
5
|
+
import { CircularExtendsError, ParseError, deepMerge, parseConfigFile } from "./shared/@outfitter/config-sp6gradd.js";
|
|
6
|
+
import { Result, ValidationError } from "@outfitter/contracts";
|
|
234
7
|
import { ZodSchema } from "zod";
|
|
235
|
-
type ParseErrorFields = {
|
|
236
|
-
/** Human-readable error message describing the parse failure */
|
|
237
|
-
message: string;
|
|
238
|
-
/** Name of the file that failed to parse */
|
|
239
|
-
filename: string;
|
|
240
|
-
/** Line number where the error occurred (if available) */
|
|
241
|
-
line?: number;
|
|
242
|
-
/** Column number where the error occurred (if available) */
|
|
243
|
-
column?: number;
|
|
244
|
-
};
|
|
245
|
-
declare const ParseErrorBase: TaggedErrorClass<"ParseError", ParseErrorFields>;
|
|
246
|
-
/**
|
|
247
|
-
* Error thrown when a configuration file cannot be parsed.
|
|
248
|
-
*
|
|
249
|
-
* Contains details about the parse failure including the filename
|
|
250
|
-
* and optionally the line/column where the error occurred.
|
|
251
|
-
*
|
|
252
|
-
* @example
|
|
253
|
-
* ```typescript
|
|
254
|
-
* const result = parseConfigFile("invalid toml [", "config.toml");
|
|
255
|
-
* if (result.isErr() && result.error._tag === "ParseError") {
|
|
256
|
-
* console.error(`Parse error in ${result.error.filename}: ${result.error.message}`);
|
|
257
|
-
* }
|
|
258
|
-
* ```
|
|
259
|
-
*/
|
|
260
|
-
declare class ParseError extends ParseErrorBase {
|
|
261
|
-
readonly category: "validation";
|
|
262
|
-
}
|
|
263
|
-
type CircularExtendsErrorFields = {
|
|
264
|
-
/** Human-readable error message */
|
|
265
|
-
message: string;
|
|
266
|
-
/** The config file paths that form the circular reference */
|
|
267
|
-
chain: string[];
|
|
268
|
-
};
|
|
269
|
-
declare const CircularExtendsErrorBase: TaggedErrorClass<"CircularExtendsError", CircularExtendsErrorFields>;
|
|
270
|
-
/**
|
|
271
|
-
* Error thrown when a circular extends reference is detected.
|
|
272
|
-
*/
|
|
273
|
-
declare class CircularExtendsError extends CircularExtendsErrorBase {
|
|
274
|
-
readonly category: "validation";
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Get the XDG config directory for an application.
|
|
278
|
-
*
|
|
279
|
-
* Uses `XDG_CONFIG_HOME` if set, otherwise defaults to `~/.config`.
|
|
280
|
-
* This follows the XDG Base Directory Specification for storing
|
|
281
|
-
* user-specific configuration files.
|
|
282
|
-
*
|
|
283
|
-
* @param appName - Application name used as subdirectory
|
|
284
|
-
* @returns Absolute path to the application's config directory
|
|
285
|
-
*
|
|
286
|
-
* @example
|
|
287
|
-
* ```typescript
|
|
288
|
-
* // With XDG_CONFIG_HOME="/custom/config"
|
|
289
|
-
* getConfigDir("myapp"); // "/custom/config/myapp"
|
|
290
|
-
*
|
|
291
|
-
* // Without XDG_CONFIG_HOME (uses default)
|
|
292
|
-
* getConfigDir("myapp"); // "/home/user/.config/myapp"
|
|
293
|
-
* ```
|
|
294
|
-
*/
|
|
295
|
-
declare function getConfigDir(appName: string): string;
|
|
296
|
-
/**
|
|
297
|
-
* Get the XDG data directory for an application.
|
|
298
|
-
*
|
|
299
|
-
* Uses `XDG_DATA_HOME` if set, otherwise defaults to `~/.local/share`.
|
|
300
|
-
* This follows the XDG Base Directory Specification for storing
|
|
301
|
-
* user-specific data files (databases, generated content, etc.).
|
|
302
|
-
*
|
|
303
|
-
* @param appName - Application name used as subdirectory
|
|
304
|
-
* @returns Absolute path to the application's data directory
|
|
305
|
-
*
|
|
306
|
-
* @example
|
|
307
|
-
* ```typescript
|
|
308
|
-
* // With XDG_DATA_HOME="/custom/data"
|
|
309
|
-
* getDataDir("myapp"); // "/custom/data/myapp"
|
|
310
|
-
*
|
|
311
|
-
* // Without XDG_DATA_HOME (uses default)
|
|
312
|
-
* getDataDir("myapp"); // "/home/user/.local/share/myapp"
|
|
313
|
-
* ```
|
|
314
|
-
*/
|
|
315
|
-
declare function getDataDir(appName: string): string;
|
|
316
|
-
/**
|
|
317
|
-
* Get the XDG cache directory for an application.
|
|
318
|
-
*
|
|
319
|
-
* Uses `XDG_CACHE_HOME` if set, otherwise defaults to `~/.cache`.
|
|
320
|
-
* This follows the XDG Base Directory Specification for storing
|
|
321
|
-
* non-essential cached data that can be regenerated.
|
|
322
|
-
*
|
|
323
|
-
* @param appName - Application name used as subdirectory
|
|
324
|
-
* @returns Absolute path to the application's cache directory
|
|
325
|
-
*
|
|
326
|
-
* @example
|
|
327
|
-
* ```typescript
|
|
328
|
-
* // With XDG_CACHE_HOME="/custom/cache"
|
|
329
|
-
* getCacheDir("myapp"); // "/custom/cache/myapp"
|
|
330
|
-
*
|
|
331
|
-
* // Without XDG_CACHE_HOME (uses default)
|
|
332
|
-
* getCacheDir("myapp"); // "/home/user/.cache/myapp"
|
|
333
|
-
* ```
|
|
334
|
-
*/
|
|
335
|
-
declare function getCacheDir(appName: string): string;
|
|
336
|
-
/**
|
|
337
|
-
* Get the XDG state directory for an application.
|
|
338
|
-
*
|
|
339
|
-
* Uses `XDG_STATE_HOME` if set, otherwise defaults to `~/.local/state`.
|
|
340
|
-
* This follows the XDG Base Directory Specification for storing
|
|
341
|
-
* state data that should persist between restarts (logs, history, etc.).
|
|
342
|
-
*
|
|
343
|
-
* @param appName - Application name used as subdirectory
|
|
344
|
-
* @returns Absolute path to the application's state directory
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* ```typescript
|
|
348
|
-
* // With XDG_STATE_HOME="/custom/state"
|
|
349
|
-
* getStateDir("myapp"); // "/custom/state/myapp"
|
|
350
|
-
*
|
|
351
|
-
* // Without XDG_STATE_HOME (uses default)
|
|
352
|
-
* getStateDir("myapp"); // "/home/user/.local/state/myapp"
|
|
353
|
-
* ```
|
|
354
|
-
*/
|
|
355
|
-
declare function getStateDir(appName: string): string;
|
|
356
|
-
/**
|
|
357
|
-
* Deep merge two objects with configurable merge semantics.
|
|
358
|
-
*
|
|
359
|
-
* Merge behavior:
|
|
360
|
-
* - Recursively merges nested plain objects
|
|
361
|
-
* - Arrays are replaced (not concatenated)
|
|
362
|
-
* - `null` explicitly replaces the target value
|
|
363
|
-
* - `undefined` is skipped (does not override)
|
|
364
|
-
*
|
|
365
|
-
* @typeParam T - The type of the target object
|
|
366
|
-
* @param target - Base object to merge into (not mutated)
|
|
367
|
-
* @param source - Object with values to merge
|
|
368
|
-
* @returns New object with merged values
|
|
369
|
-
*
|
|
370
|
-
* @example
|
|
371
|
-
* ```typescript
|
|
372
|
-
* const defaults = { server: { port: 3000, host: "localhost" } };
|
|
373
|
-
* const overrides = { server: { port: 8080 } };
|
|
374
|
-
*
|
|
375
|
-
* const merged = deepMerge(defaults, overrides);
|
|
376
|
-
* // { server: { port: 8080, host: "localhost" } }
|
|
377
|
-
* ```
|
|
378
|
-
*
|
|
379
|
-
* @example
|
|
380
|
-
* ```typescript
|
|
381
|
-
* // Arrays replace, not merge
|
|
382
|
-
* const target = { tags: ["a", "b"] };
|
|
383
|
-
* const source = { tags: ["c"] };
|
|
384
|
-
* deepMerge(target, source); // { tags: ["c"] }
|
|
385
|
-
*
|
|
386
|
-
* // undefined is skipped
|
|
387
|
-
* const base = { a: 1, b: 2 };
|
|
388
|
-
* deepMerge(base, { a: undefined, b: 3 }); // { a: 1, b: 3 }
|
|
389
|
-
*
|
|
390
|
-
* // null explicitly replaces
|
|
391
|
-
* deepMerge(base, { a: null }); // { a: null, b: 2 }
|
|
392
|
-
* ```
|
|
393
|
-
*/
|
|
394
|
-
declare function deepMerge<T extends object>(target: T, source: Partial<T>): T;
|
|
395
|
-
/**
|
|
396
|
-
* Parse configuration file content based on filename extension.
|
|
397
|
-
*
|
|
398
|
-
* Supports multiple formats:
|
|
399
|
-
* - `.toml` - Parsed with smol-toml (preferred for config)
|
|
400
|
-
* - `.yaml`, `.yml` - Parsed with yaml (merge key support enabled)
|
|
401
|
-
* - `.json` - Parsed with strict JSON.parse
|
|
402
|
-
* - `.jsonc` - Parsed with json5 compatibility (comments/trailing commas)
|
|
403
|
-
* - `.json5` - Parsed with json5 (comments and trailing commas allowed)
|
|
404
|
-
*
|
|
405
|
-
* @param content - Raw file content to parse
|
|
406
|
-
* @param filename - Filename used to determine format (by extension)
|
|
407
|
-
* @returns Result containing parsed object or ParseError
|
|
408
|
-
*
|
|
409
|
-
* @example
|
|
410
|
-
* ```typescript
|
|
411
|
-
* const toml = `
|
|
412
|
-
* [server]
|
|
413
|
-
* port = 3000
|
|
414
|
-
* host = "localhost"
|
|
415
|
-
* `;
|
|
416
|
-
*
|
|
417
|
-
* const result = parseConfigFile(toml, "config.toml");
|
|
418
|
-
* if (result.isOk()) {
|
|
419
|
-
* console.log(result.value.server.port); // 3000
|
|
420
|
-
* }
|
|
421
|
-
* ```
|
|
422
|
-
*
|
|
423
|
-
* @example
|
|
424
|
-
* ```typescript
|
|
425
|
-
* // YAML with anchors/aliases
|
|
426
|
-
* const yaml = `
|
|
427
|
-
* defaults: &defaults
|
|
428
|
-
* timeout: 5000
|
|
429
|
-
* server:
|
|
430
|
-
* <<: *defaults
|
|
431
|
-
* port: 3000
|
|
432
|
-
* `;
|
|
433
|
-
*
|
|
434
|
-
* const result = parseConfigFile(yaml, "config.yaml");
|
|
435
|
-
* if (result.isOk()) {
|
|
436
|
-
* console.log(result.value.server.timeout); // 5000
|
|
437
|
-
* }
|
|
438
|
-
* ```
|
|
439
|
-
*/
|
|
440
|
-
declare function parseConfigFile(content: string, filename: string): Result<Record<string, unknown>, InstanceType<typeof ParseError>>;
|
|
441
8
|
/**
|
|
442
9
|
* Configuration sources for multi-layer resolution.
|
|
443
10
|
*
|
|
@@ -503,73 +70,6 @@ interface ConfigSources<T> {
|
|
|
503
70
|
*/
|
|
504
71
|
declare function resolveConfig<T>(schema: ZodSchema<T>, sources: ConfigSources<T>): Result<T, InstanceType<typeof ValidationError> | InstanceType<typeof ParseError>>;
|
|
505
72
|
/**
|
|
506
|
-
* Options for the {@link loadConfig} function.
|
|
507
|
-
*
|
|
508
|
-
* @example
|
|
509
|
-
* ```typescript
|
|
510
|
-
* const options: LoadConfigOptions = {
|
|
511
|
-
* searchPaths: ["/etc/myapp", "/opt/myapp/config"],
|
|
512
|
-
* };
|
|
513
|
-
* ```
|
|
514
|
-
*/
|
|
515
|
-
interface LoadConfigOptions {
|
|
516
|
-
/**
|
|
517
|
-
* Custom search paths to check for config files.
|
|
518
|
-
* When provided, overrides the default XDG-based search paths.
|
|
519
|
-
* Paths are searched in order; first match wins.
|
|
520
|
-
*/
|
|
521
|
-
searchPaths?: string[];
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Load configuration for an application from XDG-compliant paths.
|
|
525
|
-
*
|
|
526
|
-
* Search order (first found wins):
|
|
527
|
-
* 1. Custom `searchPaths` if provided in options
|
|
528
|
-
* 2. `$XDG_CONFIG_HOME/{appName}/config.{ext}`
|
|
529
|
-
* 3. `~/.config/{appName}/config.{ext}`
|
|
530
|
-
*
|
|
531
|
-
* File format preference: `.toml` > `.yaml` > `.yml` > `.json` > `.jsonc` > `.json5`
|
|
532
|
-
*
|
|
533
|
-
* @typeParam T - The configuration type (inferred from schema)
|
|
534
|
-
* @param appName - Application name for XDG directory lookup
|
|
535
|
-
* @param schema - Zod schema for validation
|
|
536
|
-
* @param options - Optional configuration (custom search paths)
|
|
537
|
-
* @returns Result containing validated config or NotFoundError/ValidationError/ParseError
|
|
538
|
-
*
|
|
539
|
-
* @example
|
|
540
|
-
* ```typescript
|
|
541
|
-
* import { loadConfig } from "@outfitter/config";
|
|
542
|
-
* import { z } from "zod";
|
|
543
|
-
*
|
|
544
|
-
* const AppConfigSchema = z.object({
|
|
545
|
-
* apiKey: z.string(),
|
|
546
|
-
* timeout: z.number().default(5000),
|
|
547
|
-
* features: z.object({
|
|
548
|
-
* darkMode: z.boolean().default(false),
|
|
549
|
-
* }),
|
|
550
|
-
* });
|
|
551
|
-
*
|
|
552
|
-
* // Searches ~/.config/myapp/config.{toml,yaml,json,...}
|
|
553
|
-
* const result = await loadConfig("myapp", AppConfigSchema);
|
|
554
|
-
*
|
|
555
|
-
* if (result.isOk()) {
|
|
556
|
-
* console.log("API Key:", result.value.apiKey);
|
|
557
|
-
* console.log("Timeout:", result.value.timeout);
|
|
558
|
-
* } else {
|
|
559
|
-
* console.error("Failed to load config:", result.error.message);
|
|
560
|
-
* }
|
|
561
|
-
* ```
|
|
562
|
-
*
|
|
563
|
-
* @example
|
|
564
|
-
* ```typescript
|
|
565
|
-
* // With custom search paths
|
|
566
|
-
* const result = await loadConfig("myapp", AppConfigSchema, {
|
|
567
|
-
* searchPaths: ["/etc/myapp", "/opt/myapp/config"],
|
|
568
|
-
* });
|
|
569
|
-
* ```
|
|
570
|
-
*/
|
|
571
|
-
declare function loadConfig<T>(appName: string, schema: ZodSchema<T>, options?: LoadConfigOptions): Result<T, InstanceType<typeof NotFoundError> | InstanceType<typeof ValidationError> | InstanceType<typeof ParseError> | InstanceType<typeof CircularExtendsError>>;
|
|
572
|
-
/**
|
|
573
73
|
* Map environment variables to config object based on prefix.
|
|
574
74
|
*
|
|
575
75
|
* Environment variables are mapped as follows:
|