@clipboard-health/config 0.1.0 → 0.2.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
@@ -19,7 +19,76 @@ npm install @clipboard-health/config
19
19
 
20
20
  ### Type-safe configuration
21
21
 
22
- For additional detail, see the `createConfig` documentation.
22
+ The TypeDoc comment for the `createConfig` function:
23
+
24
+ <!-- prettier-ignore -->
25
+ ```ts
26
+ // ./src/lib/createConfig.ts
27
+
28
+ import { fromZodError } from "zod-validation-error";
29
+
30
+ import { deepFreeze } from "./internal/deepFreeze";
31
+ import { resolve } from "./internal/resolver";
32
+ import { type ConfigParams } from "./types";
33
+
34
+ /**
35
+ * Type-safe static configuration management: a pure function to resolve, validate against a Zod
36
+ * schema, and freeze configuration values.
37
+ *
38
+ * Configuration values resolve in order from highest precedence to lowest:
39
+ * 1. Environment variables
40
+ * - Resolved converting configuration path from camelCase to UPPER_SNAKE. For example, the `{
41
+ * myApi: { port: 3000 } }` configuration resolves to `MY_API_PORT`.
42
+ * 2. Environment-specific overrides, {@link ConfigValue.overrides}
43
+ * 3. Default values, {@link ConfigValue.defaultValue}
44
+ *
45
+ * Supported configuration value types:
46
+ * - bigint
47
+ * - boolean
48
+ * - date
49
+ * - number
50
+ * - string
51
+ * - arrays and nested objects using the above types
52
+ *
53
+ * To override arrays with environment variables, use stringified JSON arrays, e.g. `["a","b"]`.
54
+ *
55
+ * **IMPORTANT**: To avoid runtime errors:
56
+ * 1. Environment variables are strings, so use `z.coerce` Zod types for those you plan to override.
57
+ * Note that `z.coerce.boolean()` coerces any truthy value to `true`. To restrict to `"true" |
58
+ * "false"`, use the
59
+ * {@link https://github.com/ClipboardHealth/core-utils/blob/main/packages/contract-core/src/lib/schemas/booleanString.ts
60
+ * `booleanString` schema} from `@clipboard-health/contract-core`.
61
+ * 2. The resulting configuration is deeply frozen and will throw a runtime error if you attempt to
62
+ * modify it. The actual return type is `ReadonlyDeep<SchemaT>`, but the library returns a
63
+ * `Readonly<SchemaT>` because the former prevents clients from passing configuration values to
64
+ * functions that don't explicitly accept `readonly` types.
65
+ *
66
+ * @includeExample ./packages/config/examples/config.ts
67
+ * @see [Usage example](../../examples/config.ts)
68
+ *
69
+ * @throws {Error} When configuration values fail schema validation
70
+ * @returns A deeply frozen configuration object matching the provided schema
71
+ */
72
+ export function createConfig<
73
+ const SchemaT extends Record<string, unknown>,
74
+ const EnvironmentT extends readonly string[],
75
+ >(params: Readonly<ConfigParams<SchemaT, EnvironmentT>>): Readonly<SchemaT> {
76
+ const { config, environment, schema } = params;
77
+ const { current } = environment;
78
+
79
+ const result = schema.safeParse(resolve({ config, environment: current, path: [], schema }));
80
+ if (!result.success) {
81
+ throw new Error(`Configuration validation failed: ${fromZodError(result.error).toString()}`, {
82
+ cause: result.error,
83
+ });
84
+ }
85
+
86
+ return deepFreeze(result.data);
87
+ }
88
+
89
+ ```
90
+
91
+ A usage example:
23
92
 
24
93
  <!-- prettier-ignore -->
25
94
  ```ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clipboard-health/config",
3
3
  "description": "Type-safe static configuration management: a pure function to resolve, validate against a Zod schema, and freeze configuration values.",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "dependencies": {
6
6
  "decamelize": "5.0.1",
7
7
  "tslib": "2.8.0",
package/src/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./lib/config";
1
+ export * from "./lib/createConfig";
2
2
  export * from "./lib/types";
package/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./lib/config"), exports);
4
+ tslib_1.__exportStar(require("./lib/createConfig"), exports);
5
5
  tslib_1.__exportStar(require("./lib/types"), exports);
6
6
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/config/src/index.ts"],"names":[],"mappings":";;;AAAA,uDAA6B;AAC7B,sDAA4B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/config/src/index.ts"],"names":[],"mappings":";;;AAAA,6DAAmC;AACnC,sDAA4B"}
@@ -47,8 +47,10 @@ function createConfig(params) {
47
47
  const { current } = environment;
48
48
  const result = schema.safeParse((0, resolver_1.resolve)({ config, environment: current, path: [], schema }));
49
49
  if (!result.success) {
50
- throw new Error((0, zod_validation_error_1.fromZodError)(result.error).toString(), { cause: result.error });
50
+ throw new Error(`Configuration validation failed: ${(0, zod_validation_error_1.fromZodError)(result.error).toString()}`, {
51
+ cause: result.error,
52
+ });
51
53
  }
52
54
  return (0, deepFreeze_1.deepFreeze)(result.data);
53
55
  }
54
- //# sourceMappingURL=config.js.map
56
+ //# sourceMappingURL=createConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createConfig.js","sourceRoot":"","sources":["../../../../../packages/config/src/lib/createConfig.ts"],"names":[],"mappings":";;AA4CA,oCAeC;AA3DD,+DAAoD;AAEpD,sDAAmD;AACnD,kDAA8C;AAG9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,SAAgB,YAAY,CAG1B,MAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;IAEhC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAA,kBAAO,EAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAA,mCAAY,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE;YAC3F,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAA,uBAAU,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../packages/config/src/lib/config.ts"],"names":[],"mappings":";;AA4CA,oCAaC;AAzDD,+DAAoD;AAEpD,sDAAmD;AACnD,kDAA8C;AAG9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,SAAgB,YAAY,CAG1B,MAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;IAEhC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAA,kBAAO,EAAC,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,IAAA,mCAAY,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,IAAA,uBAAU,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
File without changes