@outfitter/config 0.3.3 → 0.3.4

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 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>; // Lowest precedence
198
- file?: Partial<T>; // From config file
199
- env?: Partial<T>; // Environment variables
200
- flags?: Partial<T>; // CLI flags (highest)
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[]; // Custom search paths
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 | `development` | `production` | `test` |
260
- |---------|--------------|-------------|--------|
261
- | logLevel | `"debug"` | `null` | `null` |
262
- | verbose | `true` | `false` | `false` |
263
- | errorDetail | `"full"` | `"message"` | `"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 | macOS/Linux Default | Purpose |
290
- |----------|---------------------|---------|
291
- | `XDG_CONFIG_HOME` | `~/.config` | User-specific configuration |
292
- | `XDG_DATA_HOME` | `~/.local/share` | User-specific data files |
293
- | `XDG_CACHE_HOME` | `~/.cache` | Non-essential cached data |
294
- | `XDG_STATE_HOME` | `~/.local/state` | Persistent state (logs, history) |
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 | Parser | Notes |
321
- |-----------|--------|-------|
322
- | `.toml` | smol-toml | Preferred for configuration |
323
- | `.yaml`, `.yml` | yaml | YAML anchors/aliases supported |
324
- | `.json` | JSON.parse | Strict parsing |
325
- | `.jsonc` | json5 | JSON with comments and trailing commas |
326
- | `.json5` | json5 | Comments and trailing commas allowed |
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,234 +1,5 @@
1
- /**
2
- * Unified environment profiles for Outfitter packages.
3
- *
4
- * Provides a shared "environment" concept that cascades defaults
5
- * across all Outfitter packages. The environment is determined by
6
- * the `OUTFITTER_ENV` environment variable, falling back to
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;
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";
232
3
  import { TaggedErrorClass } from "@outfitter/contracts";
233
4
  import { NotFoundError, Result, ValidationError } from "@outfitter/contracts";
234
5
  import { ZodSchema } from "zod";
package/dist/index.js CHANGED
@@ -1,71 +1,20 @@
1
- // src/environment.ts
2
- var VALID_ENVIRONMENTS = new Set([
3
- "development",
4
- "production",
5
- "test"
6
- ]);
7
- var ENVIRONMENT_DEFAULTS = {
8
- development: {
9
- logLevel: "debug",
10
- verbose: true,
11
- errorDetail: "full"
12
- },
13
- production: {
14
- logLevel: null,
15
- verbose: false,
16
- errorDetail: "message"
17
- },
18
- test: {
19
- logLevel: null,
20
- verbose: false,
21
- errorDetail: "full"
22
- }
23
- };
24
- function getEnvironment() {
25
- const value = process.env["OUTFITTER_ENV"];
26
- if (value !== undefined && VALID_ENVIRONMENTS.has(value)) {
27
- return value;
28
- }
29
- return "production";
30
- }
31
- function getEnvironmentDefaults(env) {
32
- return { ...ENVIRONMENT_DEFAULTS[env] };
33
- }
34
- // src/env.ts
35
- import { z } from "zod";
36
- var portSchema = z.string().regex(/^\d+$/).transform(Number).pipe(z.number().int().positive().max(65535));
37
- var booleanSchema = z.enum(["true", "false", "1", "0", ""]).transform((val) => val === "true" || val === "1");
38
- var optionalBooleanSchema = z.string().optional().transform((val) => {
39
- if (val === undefined || val === "")
40
- return;
41
- return val === "true" || val === "1";
42
- });
43
- function parseEnv(schema, envObj = process.env) {
44
- return schema.parse(envObj);
45
- }
46
- var appEnvSchema = z.object({
47
- NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
48
- NO_COLOR: optionalBooleanSchema,
49
- FORCE_COLOR: optionalBooleanSchema,
50
- CI: optionalBooleanSchema,
51
- TERM: z.string().optional(),
52
- XDG_CONFIG_HOME: z.string().optional(),
53
- XDG_DATA_HOME: z.string().optional(),
54
- XDG_STATE_HOME: z.string().optional(),
55
- XDG_CACHE_HOME: z.string().optional(),
56
- HOME: z.string().optional()
57
- });
58
- var env = parseEnv(appEnvSchema);
59
- function getEnvBoolean(key) {
60
- const value = process.env[key];
61
- if (value === undefined || value === "")
62
- return;
63
- return value === "true" || value === "1";
64
- }
1
+ // @bun
2
+ import {
3
+ booleanSchema,
4
+ env,
5
+ getEnvBoolean,
6
+ optionalBooleanSchema,
7
+ parseEnv,
8
+ portSchema
9
+ } from "./shared/@outfitter/config-443pb6p2.js";
10
+ import {
11
+ getEnvironment,
12
+ getEnvironmentDefaults
13
+ } from "./shared/@outfitter/config-w3pwcpr2.js";
65
14
 
66
- // src/index.ts
67
- import { existsSync, readFileSync } from "node:fs";
68
- import { dirname, isAbsolute, join, resolve } from "node:path";
15
+ // packages/config/src/index.ts
16
+ import { existsSync, readFileSync } from "fs";
17
+ import { dirname, isAbsolute, join, resolve } from "path";
69
18
  import {
70
19
  NotFoundError,
71
20
  Result,
package/package.json CHANGED
@@ -1,11 +1,24 @@
1
1
  {
2
2
  "name": "@outfitter/config",
3
+ "version": "0.3.4",
3
4
  "description": "XDG-compliant config loading with schema validation for Outfitter",
4
- "version": "0.3.3",
5
- "type": "module",
5
+ "keywords": [
6
+ "config",
7
+ "outfitter",
8
+ "typescript",
9
+ "xdg"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/outfitter-dev/outfitter.git",
15
+ "directory": "packages/config"
16
+ },
6
17
  "files": [
7
18
  "dist"
8
19
  ],
20
+ "type": "module",
21
+ "sideEffects": false,
9
22
  "module": "./dist/index.js",
10
23
  "types": "./dist/index.d.ts",
11
24
  "exports": {
@@ -29,40 +42,27 @@
29
42
  },
30
43
  "./package.json": "./package.json"
31
44
  },
32
- "sideEffects": false,
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
33
48
  "scripts": {
34
- "build": "bunup --filter @outfitter/config",
35
- "lint": "biome lint ./src",
36
- "lint:fix": "biome lint --write ./src",
49
+ "build": "cd ../.. && bunup --filter @outfitter/config",
50
+ "lint": "oxlint ./src",
51
+ "lint:fix": "oxlint --fix ./src",
37
52
  "test": "bun test",
38
53
  "typecheck": "tsc --noEmit",
39
54
  "clean": "rm -rf dist",
40
55
  "prepublishOnly": "bun ../../scripts/check-publish-manifest.ts"
41
56
  },
42
57
  "dependencies": {
43
- "@outfitter/contracts": "0.4.1",
44
- "@outfitter/types": "0.2.3",
58
+ "@outfitter/contracts": "0.4.2",
59
+ "@outfitter/types": "0.2.4",
45
60
  "smol-toml": "^1.6.0",
46
61
  "yaml": "^2.8.2",
47
62
  "zod": "^4.3.5"
48
63
  },
49
64
  "devDependencies": {
50
- "@types/bun": "latest",
51
- "typescript": "^5.8.0"
52
- },
53
- "keywords": [
54
- "outfitter",
55
- "config",
56
- "xdg",
57
- "typescript"
58
- ],
59
- "license": "MIT",
60
- "repository": {
61
- "type": "git",
62
- "url": "https://github.com/outfitter-dev/outfitter.git",
63
- "directory": "packages/config"
64
- },
65
- "publishConfig": {
66
- "access": "public"
65
+ "@types/bun": "^1.3.9",
66
+ "typescript": "^5.9.3"
67
67
  }
68
68
  }