@clipboard-health/config 0.1.0 → 0.2.1

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,79 @@ 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 dotenv from "dotenv";
29
+ import { fromZodError } from "zod-validation-error";
30
+
31
+ import { deepFreeze } from "./internal/deepFreeze";
32
+ import { resolve } from "./internal/resolver";
33
+ import { type ConfigParams } from "./types";
34
+
35
+ dotenv.config();
36
+
37
+ /**
38
+ * Type-safe static configuration management: a pure function to resolve, validate against a Zod
39
+ * schema, and freeze configuration values.
40
+ *
41
+ * Configuration values resolve in order from highest precedence to lowest:
42
+ * 1. Environment variables
43
+ * - Resolved converting configuration path from camelCase to UPPER_SNAKE. For example, the `{
44
+ * myApi: { port: 3000 } }` configuration resolves to `MY_API_PORT`.
45
+ * 2. Environment-specific overrides, {@link ConfigValue.overrides}
46
+ * 3. Default values, {@link ConfigValue.defaultValue}
47
+ *
48
+ * Supported configuration value types:
49
+ * - bigint
50
+ * - boolean
51
+ * - date
52
+ * - number
53
+ * - string
54
+ * - arrays and nested objects using the above types
55
+ *
56
+ * To override arrays with environment variables, use stringified JSON arrays, e.g. `["a","b"]`.
57
+ *
58
+ * **IMPORTANT**: To avoid runtime errors:
59
+ * 1. Environment variables are strings, so use `z.coerce` Zod types for those you plan to override.
60
+ * Note that `z.coerce.boolean()` coerces any truthy value to `true`. To restrict to `"true" |
61
+ * "false"`, use the
62
+ * {@link https://github.com/ClipboardHealth/core-utils/blob/main/packages/contract-core/src/lib/schemas/booleanString.ts
63
+ * `booleanString` schema} from `@clipboard-health/contract-core`.
64
+ * 2. The resulting configuration is deeply frozen and will throw a runtime error if you attempt to
65
+ * modify it. The actual return type is `ReadonlyDeep<SchemaT>`, but the library returns a
66
+ * `Readonly<SchemaT>` because the former prevents clients from passing configuration values to
67
+ * functions that don't explicitly accept `readonly` types.
68
+ *
69
+ * @includeExample ./packages/config/examples/config.ts
70
+ * @see [Usage example](../../examples/config.ts)
71
+ *
72
+ * @throws {Error} When configuration values fail schema validation
73
+ * @returns A deeply frozen configuration object matching the provided schema
74
+ */
75
+ export function createConfig<
76
+ const SchemaT extends Record<string, unknown>,
77
+ const EnvironmentT extends readonly string[],
78
+ >(params: Readonly<ConfigParams<SchemaT, EnvironmentT>>): Readonly<SchemaT> {
79
+ const { config, environment, schema } = params;
80
+ const { current } = environment;
81
+
82
+ const result = schema.safeParse(resolve({ config, environment: current, path: [], schema }));
83
+ if (!result.success) {
84
+ throw new Error(`Configuration validation failed: ${fromZodError(result.error).toString()}`, {
85
+ cause: result.error,
86
+ });
87
+ }
88
+
89
+ return deepFreeze(result.data);
90
+ }
91
+
92
+ ```
93
+
94
+ A usage example:
23
95
 
24
96
  <!-- prettier-ignore -->
25
97
  ```ts
package/package.json CHANGED
@@ -1,21 +1,22 @@
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.1",
5
5
  "dependencies": {
6
6
  "decamelize": "5.0.1",
7
+ "dotenv": "16.4.5",
7
8
  "tslib": "2.8.0",
8
9
  "zod": "3.23.8",
9
10
  "zod-validation-error": "3.4.0"
10
11
  },
11
12
  "devDependencies": {
12
- "@clipboard-health/contract-core": "0.2.0"
13
+ "@clipboard-health/contract-core": "0.3.0"
13
14
  },
14
15
  "keywords": [],
15
16
  "license": "MIT",
16
17
  "main": "./src/index.js",
17
18
  "publishConfig": {
18
- "access": "restricted"
19
+ "access": "public"
19
20
  },
20
21
  "scripts": {
21
22
  "embed": "embedme README.md"
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"}
@@ -1,9 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createConfig = createConfig;
4
+ const tslib_1 = require("tslib");
5
+ const dotenv_1 = tslib_1.__importDefault(require("dotenv"));
4
6
  const zod_validation_error_1 = require("zod-validation-error");
5
7
  const deepFreeze_1 = require("./internal/deepFreeze");
6
8
  const resolver_1 = require("./internal/resolver");
9
+ dotenv_1.default.config();
7
10
  /**
8
11
  * Type-safe static configuration management: a pure function to resolve, validate against a Zod
9
12
  * schema, and freeze configuration values.
@@ -47,8 +50,10 @@ function createConfig(params) {
47
50
  const { current } = environment;
48
51
  const result = schema.safeParse((0, resolver_1.resolve)({ config, environment: current, path: [], schema }));
49
52
  if (!result.success) {
50
- throw new Error((0, zod_validation_error_1.fromZodError)(result.error).toString(), { cause: result.error });
53
+ throw new Error(`Configuration validation failed: ${(0, zod_validation_error_1.fromZodError)(result.error).toString()}`, {
54
+ cause: result.error,
55
+ });
51
56
  }
52
57
  return (0, deepFreeze_1.deepFreeze)(result.data);
53
58
  }
54
- //# sourceMappingURL=config.js.map
59
+ //# sourceMappingURL=createConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createConfig.js","sourceRoot":"","sources":["../../../../../packages/config/src/lib/createConfig.ts"],"names":[],"mappings":";;AA+CA,oCAeC;;AA9DD,4DAA4B;AAC5B,+DAAoD;AAEpD,sDAAmD;AACnD,kDAA8C;AAG9C,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../../../packages/config/src/lib/internal/resolver.ts"],"names":[],"mappings":";;AAoBA,0BAeC;;AAnCD,oEAAoC;AACpC,6BAAwB;AAGxB,2CAAwC;AAgBxC,SAAgB,OAAO,CACrB,MAAwC;IAExC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAEzC,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CACxB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAuD,EAAE,EAAE,CAAC;QACtE,GAAG;QACH,aAAa,CAAC,KAAK,CAAC;YAClB,CAAC,CAAC,kBAAkB,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;YAC9D,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;KAC9D,CACF,CACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,IAAA,qBAAS,EAAC,KAAK,CAAC;QAChB,aAAa,IAAI,KAAK;QACtB,cAAc,IAAI,KAAK,CACxB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAgC;IAC1D,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAA,oBAAU,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACvE,IAAI,IAAA,qBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,wBAAwB,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,IAAA,qBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,YAAY,CAAC;AAC5B,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc,EAAE,MAA0B;IAC1E,IAAI,MAAM,YAAY,OAAC,CAAC,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9D,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB,EAAE,MAA0B;IACpE,OAAO,IAAI,CAAC,MAAM,CAChB,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;IACd,+DAA+D;IAC/D,MAAM,YAAY,OAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,MAAM,EACvF,MAAM,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../../../packages/config/src/lib/internal/resolver.ts"],"names":[],"mappings":";;AAiBA,0BAeC;;AAhCD,oEAAoC;AACpC,6BAAwB;AAGxB,2CAAwC;AAaxC,SAAgB,OAAO,CACrB,MAAwC;IAExC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAEzC,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CACxB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAuD,EAAE,EAAE,CAAC;QACtE,GAAG;QACH,aAAa,CAAC,KAAK,CAAC;YAClB,CAAC,CAAC,kBAAkB,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;YAC9D,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;KAC9D,CACF,CACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,IAAA,qBAAS,EAAC,KAAK,CAAC;QAChB,aAAa,IAAI,KAAK;QACtB,cAAc,IAAI,KAAK,CACxB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAgC;IAC1D,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAA,oBAAU,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACvE,IAAI,IAAA,qBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,wBAAwB,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,IAAA,qBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,YAAY,CAAC;AAC5B,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc,EAAE,MAA0B;IAC1E,IAAI,MAAM,YAAY,OAAC,CAAC,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9D,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB,EAAE,MAA0B;IACpE,OAAO,IAAI,CAAC,MAAM,CAChB,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;IACd,+DAA+D;IAC/D,MAAM,YAAY,OAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,MAAM,EACvF,MAAM,CACP,CAAC;AACJ,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