@outfitter/config 0.1.0 → 0.3.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 CHANGED
@@ -68,7 +68,7 @@ if (result.isOk()) {
68
68
  2. `$XDG_CONFIG_HOME/{appName}/config.{ext}`
69
69
  3. `~/.config/{appName}/config.{ext}`
70
70
 
71
- **File Format Preference:** `.toml` > `.yaml` > `.yml` > `.json` > `.json5`
71
+ **File Format Preference:** `.toml` > `.yaml` > `.yml` > `.json` > `.jsonc` > `.json5`
72
72
 
73
73
  **Returns:** `Result<T, NotFoundError | ValidationError | ParseError>`
74
74
 
@@ -227,6 +227,61 @@ class ParseError {
227
227
 
228
228
  ---
229
229
 
230
+ ## Environment Profiles
231
+
232
+ Unified environment detection for consistent defaults across all Outfitter packages.
233
+
234
+ ### `getEnvironment()`
235
+
236
+ Reads `OUTFITTER_ENV` and returns the current profile. Falls back to `"production"` when unset or invalid.
237
+
238
+ ```typescript
239
+ import { getEnvironment } from "@outfitter/config";
240
+
241
+ const env = getEnvironment();
242
+ // "development" | "production" | "test"
243
+ ```
244
+
245
+ ### `getEnvironmentDefaults(env)`
246
+
247
+ Returns profile-specific defaults for an environment.
248
+
249
+ ```typescript
250
+ import { getEnvironmentDefaults } from "@outfitter/config";
251
+
252
+ const defaults = getEnvironmentDefaults("development");
253
+ // { logLevel: "debug", verbose: true, errorDetail: "full" }
254
+
255
+ const prodDefaults = getEnvironmentDefaults("production");
256
+ // { logLevel: null, verbose: false, errorDetail: "message" }
257
+ ```
258
+
259
+ | Setting | `development` | `production` | `test` |
260
+ |---------|--------------|-------------|--------|
261
+ | logLevel | `"debug"` | `null` | `null` |
262
+ | verbose | `true` | `false` | `false` |
263
+ | errorDetail | `"full"` | `"message"` | `"full"` |
264
+
265
+ ### Types
266
+
267
+ #### `OutfitterEnv`
268
+
269
+ ```typescript
270
+ type OutfitterEnv = "development" | "production" | "test";
271
+ ```
272
+
273
+ #### `EnvironmentDefaults`
274
+
275
+ ```typescript
276
+ interface EnvironmentDefaults {
277
+ logLevel: "debug" | "info" | "warn" | "error" | null;
278
+ verbose: boolean;
279
+ errorDetail: "full" | "message";
280
+ }
281
+ ```
282
+
283
+ ---
284
+
230
285
  ## XDG Base Directory Specification
231
286
 
232
287
  This package follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) for locating configuration files.
@@ -267,6 +322,7 @@ Higher precedence sources override lower ones. Nested objects are deep-merged.
267
322
  | `.toml` | smol-toml | Preferred for configuration |
268
323
  | `.yaml`, `.yml` | yaml | YAML anchors/aliases supported |
269
324
  | `.json` | JSON.parse | Strict parsing |
325
+ | `.jsonc` | json5 | JSON with comments and trailing commas |
270
326
  | `.json5` | json5 | Comments and trailing commas allowed |
271
327
 
272
328
  ---
package/dist/index.d.ts CHANGED
@@ -1,3 +1,92 @@
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
+ /** Default log level. `null` means logging is disabled by default. */
39
+ logLevel: "debug" | "info" | "warn" | "error" | null;
40
+ /** Whether verbose output is enabled by default. */
41
+ verbose: boolean;
42
+ /** How much error detail to include in output. */
43
+ errorDetail: "full" | "message";
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;
1
90
  import { z } from "zod";
2
91
  /**
3
92
  * Port number schema (1-65535) with string-to-number coercion.
@@ -310,6 +399,7 @@ declare function deepMerge<T extends object>(target: T, source: Partial<T>): T;
310
399
  * - `.toml` - Parsed with smol-toml (preferred for config)
311
400
  * - `.yaml`, `.yml` - Parsed with yaml (merge key support enabled)
312
401
  * - `.json` - Parsed with strict JSON.parse
402
+ * - `.jsonc` - Parsed with json5 compatibility (comments/trailing commas)
313
403
  * - `.json5` - Parsed with json5 (comments and trailing commas allowed)
314
404
  *
315
405
  * @param content - Raw file content to parse
@@ -438,7 +528,7 @@ interface LoadConfigOptions {
438
528
  * 2. `$XDG_CONFIG_HOME/{appName}/config.{ext}`
439
529
  * 3. `~/.config/{appName}/config.{ext}`
440
530
  *
441
- * File format preference: `.toml` > `.yaml` > `.yml` > `.json` > `.json5`
531
+ * File format preference: `.toml` > `.yaml` > `.yml` > `.json` > `.jsonc` > `.json5`
442
532
  *
443
533
  * @typeParam T - The configuration type (inferred from schema)
444
534
  * @param appName - Application name for XDG directory lookup
@@ -508,4 +598,4 @@ declare function loadConfig<T>(appName: string, schema: ZodSchema<T>, options?:
508
598
  * ```
509
599
  */
510
600
  declare function mapEnvToConfig<T>(prefix: string, _schema?: ZodSchema<T>): Partial<T>;
511
- export { resolveConfig, portSchema, parseEnv, parseConfigFile, optionalBooleanSchema, mapEnvToConfig, loadConfig, getStateDir, getEnvBoolean, getDataDir, getConfigDir, getCacheDir, env, deepMerge, booleanSchema, ParseError, LoadConfigOptions, Env, ConfigSources, CircularExtendsError };
601
+ export { resolveConfig, portSchema, parseEnv, parseConfigFile, optionalBooleanSchema, mapEnvToConfig, loadConfig, getStateDir, getEnvironmentDefaults, getEnvironment, getEnvBoolean, getDataDir, getConfigDir, getCacheDir, env, deepMerge, booleanSchema, ParseError, OutfitterEnv, LoadConfigOptions, EnvironmentDefaults, Env, ConfigSources, CircularExtendsError };
package/dist/index.js CHANGED
@@ -8034,6 +8034,39 @@ var require_public_api = __commonJS((exports) => {
8034
8034
  exports.stringify = stringify2;
8035
8035
  });
8036
8036
 
8037
+ // src/environment.ts
8038
+ var VALID_ENVIRONMENTS = new Set([
8039
+ "development",
8040
+ "production",
8041
+ "test"
8042
+ ]);
8043
+ var ENVIRONMENT_DEFAULTS = {
8044
+ development: {
8045
+ logLevel: "debug",
8046
+ verbose: true,
8047
+ errorDetail: "full"
8048
+ },
8049
+ production: {
8050
+ logLevel: null,
8051
+ verbose: false,
8052
+ errorDetail: "message"
8053
+ },
8054
+ test: {
8055
+ logLevel: null,
8056
+ verbose: false,
8057
+ errorDetail: "full"
8058
+ }
8059
+ };
8060
+ function getEnvironment() {
8061
+ const value = process.env["OUTFITTER_ENV"];
8062
+ if (value !== undefined && VALID_ENVIRONMENTS.has(value)) {
8063
+ return value;
8064
+ }
8065
+ return "production";
8066
+ }
8067
+ function getEnvironmentDefaults(env) {
8068
+ return { ...ENVIRONMENT_DEFAULTS[env] };
8069
+ }
8037
8070
  // src/env.ts
8038
8071
  import { z } from "zod";
8039
8072
  var portSchema = z.string().regex(/^\d+$/).transform(Number).pipe(z.number().int().positive().max(65535));
@@ -9159,6 +9192,7 @@ function parseConfigFile(content, filename) {
9159
9192
  const parsed = JSON.parse(content);
9160
9193
  return Result.ok(parsed);
9161
9194
  }
9195
+ case "jsonc":
9162
9196
  case "json5": {
9163
9197
  const parsed = import_json5.default.parse(content);
9164
9198
  return Result.ok(parsed);
@@ -9206,7 +9240,7 @@ function resolveConfig(schema, sources) {
9206
9240
  }
9207
9241
  return Result.ok(parseResult.data);
9208
9242
  }
9209
- var CONFIG_EXTENSIONS = ["toml", "yaml", "yml", "json", "json5"];
9243
+ var CONFIG_EXTENSIONS = ["toml", "yaml", "yml", "json", "jsonc", "json5"];
9210
9244
  function findConfigFile(dir) {
9211
9245
  for (const ext of CONFIG_EXTENSIONS) {
9212
9246
  const filePath = join(dir, `config.${ext}`);
@@ -9355,6 +9389,8 @@ export {
9355
9389
  mapEnvToConfig,
9356
9390
  loadConfig,
9357
9391
  getStateDir,
9392
+ getEnvironmentDefaults,
9393
+ getEnvironment,
9358
9394
  getEnvBoolean,
9359
9395
  getDataDir,
9360
9396
  getConfigDir,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@outfitter/config",
3
3
  "description": "XDG-compliant config loading with schema validation for Outfitter",
4
- "version": "0.1.0",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -9,12 +9,24 @@
9
9
  "module": "./dist/index.js",
10
10
  "types": "./dist/index.d.ts",
11
11
  "exports": {
12
+ "./environment": {
13
+ "import": {
14
+ "types": "./dist/environment.d.ts",
15
+ "default": "./dist/environment.js"
16
+ }
17
+ },
12
18
  ".": {
13
19
  "import": {
14
20
  "types": "./dist/index.d.ts",
15
21
  "default": "./dist/index.js"
16
22
  }
17
23
  },
24
+ "./env": {
25
+ "import": {
26
+ "types": "./dist/env.d.ts",
27
+ "default": "./dist/env.js"
28
+ }
29
+ },
18
30
  "./package.json": "./package.json"
19
31
  },
20
32
  "sideEffects": false,
@@ -27,8 +39,8 @@
27
39
  "clean": "rm -rf dist"
28
40
  },
29
41
  "dependencies": {
30
- "@outfitter/contracts": "0.1.0",
31
- "@outfitter/types": "0.1.0",
42
+ "@outfitter/contracts": "0.2.0",
43
+ "@outfitter/types": "0.2.0",
32
44
  "zod": "^4.3.5"
33
45
  },
34
46
  "devDependencies": {