@pawells/config 2.3.1 → 3.0.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 +252 -149
- package/dist/errors.d.ts +24 -32
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +34 -37
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/manager.d.ts +265 -46
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +667 -137
- package/dist/manager.js.map +1 -1
- package/dist/provider.d.ts +280 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +108 -0
- package/dist/provider.js.map +1 -0
- package/dist/schema.factory.d.ts +30 -37
- package/dist/schema.factory.d.ts.map +1 -1
- package/dist/schema.factory.js +59 -92
- package/dist/schema.factory.js.map +1 -1
- package/dist/secret.d.ts +13 -2
- package/dist/secret.d.ts.map +1 -1
- package/dist/secret.js +31 -6
- package/dist/secret.js.map +1 -1
- package/package.json +63 -49
- package/CHANGELOG.md +0 -19
package/dist/schema.factory.js
CHANGED
|
@@ -1,100 +1,88 @@
|
|
|
1
1
|
import { ConfigManager } from './manager.js';
|
|
2
2
|
import { IsMarkedSecret } from './secret.js';
|
|
3
|
-
import {
|
|
4
|
-
/**
|
|
5
|
-
* Intelligently parse an environment variable string to a JSON-compatible value.
|
|
6
|
-
* Attempts to parse as JSON first (handles objects, arrays, booleans, null, numbers).
|
|
7
|
-
* Falls back to treating as a plain string if JSON parsing fails.
|
|
8
|
-
*
|
|
9
|
-
* @param envVarValue - Environment variable value (always a string from process.env)
|
|
10
|
-
* @returns Parsed value (JSON-parsed if applicable, otherwise the original string)
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* parseEnvVarValue('true') → true (boolean)
|
|
14
|
-
* parseEnvVarValue('123') → 123 (number)
|
|
15
|
-
* parseEnvVarValue('["a","b"]') → ['a', 'b'] (array)
|
|
16
|
-
* parseEnvVarValue('hello') → 'hello' (string, unchanged)
|
|
17
|
-
*/
|
|
18
|
-
function ParseEnvVarValue(envVarValue) {
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(envVarValue);
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
// If JSON parsing fails, treat as a plain string
|
|
24
|
-
return envVarValue;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
3
|
+
import { ConfigNotRegisteredError, ConfigNotSetError } from './errors.js';
|
|
27
4
|
/**
|
|
28
5
|
* Safely extracts the default value from a Zod schema, handling both
|
|
29
6
|
* lazy defaults (functions) and eager defaults (plain values).
|
|
7
|
+
* Traverses wrapper schemas (ZodDefault, ZodOptional, ZodNullable, etc.)
|
|
8
|
+
* to find the default value.
|
|
30
9
|
*
|
|
31
10
|
* @param schema - The field schema to extract the default from
|
|
32
11
|
* @returns The evaluated default value, or undefined if not present
|
|
12
|
+
* @remarks Returns `undefined` in two distinct cases: (1) the schema has no `ZodDefault` wrapper, and (2) the `ZodDefault` wrapper explicitly wraps `undefined` as its default value. Callers cannot distinguish these cases from the return value alone.
|
|
33
13
|
*/
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
14
|
+
function ExtractDefaultValue(schema) {
|
|
15
|
+
let current = schema;
|
|
16
|
+
while (current != null) {
|
|
17
|
+
const def = current.def;
|
|
18
|
+
if (def != null && 'defaultValue' in def) {
|
|
19
|
+
return def.defaultValue;
|
|
20
|
+
}
|
|
21
|
+
const inner = current.unwrap;
|
|
22
|
+
if (typeof inner === 'function') {
|
|
23
|
+
current = inner.call(current);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
43
30
|
}
|
|
44
31
|
/**
|
|
45
|
-
*
|
|
32
|
+
* Registers a configuration schema with {@link ConfigManager} and returns a typed
|
|
33
|
+
* accessor object for the namespace.
|
|
34
|
+
*
|
|
35
|
+
* All schema fields are registered with {@link ConfigManager} immediately when this
|
|
36
|
+
* function is called. The name is used to derive the environment variable prefix:
|
|
37
|
+
* `name.toUpperCase() + '_'` (e.g. `'Keycloak'` → `KEYCLOAK_`).
|
|
46
38
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
39
|
+
* **Important:** Call {@link ConfigManager.RegisterProvider} for all providers before
|
|
40
|
+
* importing any module that calls `RegisterConfigSchema` so that provider values are
|
|
41
|
+
* available when schemas are registered.
|
|
50
42
|
*
|
|
51
|
-
* @param
|
|
52
|
-
* @param
|
|
53
|
-
* @returns
|
|
54
|
-
* @
|
|
43
|
+
* @param name - Human-readable namespace name; used to derive the env var prefix
|
|
44
|
+
* @param schema - Zod object schema defining the config shape and validation rules
|
|
45
|
+
* @returns {@link IConfigSchemaObject} with typed accessor methods
|
|
46
|
+
* @throws {ConfigurationError} If any field's default value does not satisfy its schema
|
|
55
47
|
*
|
|
56
48
|
* @example
|
|
57
49
|
* ```typescript
|
|
58
|
-
* const
|
|
59
|
-
*
|
|
60
|
-
*
|
|
50
|
+
* const KEYCLOAK_SCHEMA = z.object({
|
|
51
|
+
* AUTH_SERVER_URL: z.string().url().default('http://localhost:8080/auth'),
|
|
52
|
+
* REALM: z.string().min(1).default('master'),
|
|
61
53
|
* });
|
|
62
54
|
*
|
|
63
|
-
* export const
|
|
64
|
-
* //
|
|
65
|
-
* //
|
|
66
|
-
* // const host = MongoDBConfig.Get('HOST');
|
|
67
|
-
* // MongoDBConfig.Set('PORT', 27018);
|
|
68
|
-
* // MongoDBConfig.ParseENV();
|
|
55
|
+
* export const KeycloakConfig = RegisterConfigSchema('Keycloak', KEYCLOAK_SCHEMA);
|
|
56
|
+
* // → prefix is 'KEYCLOAK_'; fields registered immediately
|
|
57
|
+
* // → KeycloakConfig.Get('AUTH_SERVER_URL') returns the resolved value
|
|
69
58
|
* ```
|
|
70
59
|
*/
|
|
71
|
-
export function
|
|
72
|
-
|
|
60
|
+
export function RegisterConfigSchema(name, schema) {
|
|
61
|
+
const prefix = `${name.toUpperCase()}_`;
|
|
62
|
+
ConfigManager.RegisterNamespace(name, prefix);
|
|
63
|
+
// Build a map of key -> prefixed name, a set of secret keys, and register all fields in a single pass
|
|
73
64
|
const prefixedNames = {};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
const secretKeys = new Set();
|
|
66
|
+
for (const key of Object.keys(schema.shape)) {
|
|
67
|
+
const prefixedKey = prefix ? `${prefix}${key}` : key;
|
|
68
|
+
prefixedNames[key] = prefixedKey;
|
|
69
|
+
const fieldSchema = schema.shape[key];
|
|
70
|
+
if (IsMarkedSecret(fieldSchema)) {
|
|
71
|
+
secretKeys.add(key);
|
|
77
72
|
}
|
|
73
|
+
// Register schema field with its default value
|
|
74
|
+
const defaultValue = ExtractDefaultValue(fieldSchema);
|
|
75
|
+
// Type: Register accepts ZodTypeAny; runtime enforcement via AssertConfigValueType
|
|
76
|
+
ConfigManager.Register(prefixedKey, fieldSchema, defaultValue);
|
|
78
77
|
}
|
|
79
|
-
// Build a set of secret keys by checking each field's metadata
|
|
80
|
-
const secretKeys = new Set(Object.keys(schema.shape).filter((key) => IsMarkedSecret(schema.shape[key])));
|
|
81
78
|
return {
|
|
82
|
-
|
|
83
|
-
for (const key in schema.shape) {
|
|
84
|
-
if (Object.prototype.hasOwnProperty.call(schema.shape, key)) {
|
|
85
|
-
const fieldSchema = schema.shape[key];
|
|
86
|
-
// Safely extract default value from Zod's internal structure
|
|
87
|
-
const defaultValue = extractDefaultValue(fieldSchema);
|
|
88
|
-
// @ts-expect-error Zod schema shape types don't align with ConfigManager.Register signature, but this is safe at runtime
|
|
89
|
-
ConfigManager.Register(prefixedNames[key], fieldSchema, defaultValue);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
},
|
|
79
|
+
name,
|
|
93
80
|
Get(key) {
|
|
94
81
|
return ConfigManager.Get(prefixedNames[key]);
|
|
95
82
|
},
|
|
96
83
|
Set(key, value, source = 'OVERRIDE') {
|
|
97
|
-
//
|
|
84
|
+
// Type: TConfig[K] maps to TConfigValueTypes at runtime via Zod schema validation.
|
|
85
|
+
// The schema was validated at registration (line 190), so this cast is safe.
|
|
98
86
|
ConfigManager.Set(prefixedNames[key], value, source);
|
|
99
87
|
},
|
|
100
88
|
Validate(key, value) {
|
|
@@ -107,27 +95,6 @@ export function CreateConfigSchema(schema, prefix) {
|
|
|
107
95
|
return false;
|
|
108
96
|
}
|
|
109
97
|
},
|
|
110
|
-
ParseENV(throwOnError = false) {
|
|
111
|
-
for (const key in schema.shape) {
|
|
112
|
-
if (Object.prototype.hasOwnProperty.call(schema.shape, key)) {
|
|
113
|
-
const envVarName = prefixedNames[key];
|
|
114
|
-
const envVarValue = process.env[envVarName];
|
|
115
|
-
if (envVarValue !== undefined) {
|
|
116
|
-
try {
|
|
117
|
-
const fieldSchema = schema.shape[key];
|
|
118
|
-
// Pre-process env var string: try JSON parsing first, fall back to plain string
|
|
119
|
-
const preProcessedValue = ParseEnvVarValue(envVarValue);
|
|
120
|
-
const parsedValue = fieldSchema.parse(preProcessedValue);
|
|
121
|
-
this.Set(key, parsedValue, 'OVERRIDE');
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
if (throwOnError)
|
|
125
|
-
throw error;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
98
|
IsSecret(key) {
|
|
132
99
|
return secretKeys.has(key);
|
|
133
100
|
},
|
|
@@ -142,8 +109,8 @@ export function CreateConfigSchema(schema, prefix) {
|
|
|
142
109
|
result[key] = secretKeys.has(key) ? '***' : value;
|
|
143
110
|
}
|
|
144
111
|
catch (error) {
|
|
145
|
-
if (error instanceof
|
|
146
|
-
error instanceof
|
|
112
|
+
if (error instanceof ConfigNotSetError
|
|
113
|
+
|| error instanceof ConfigNotRegisteredError) {
|
|
147
114
|
// omit unregistered/unset keys
|
|
148
115
|
continue;
|
|
149
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.factory.js","sourceRoot":"","sources":["../src/schema.factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"schema.factory.js","sourceRoot":"","sources":["../src/schema.factory.ts"],"names":[],"mappings":"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"}
|
package/dist/secret.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { z } from 'zod/v4';
|
|
|
12
12
|
*
|
|
13
13
|
* @remarks
|
|
14
14
|
* The inferred TypeScript type is unchanged and will not affect type inference
|
|
15
|
-
* for values validated by this schema.
|
|
15
|
+
* for values validated by this schema. RegisterConfigSchema automatically detects
|
|
16
16
|
* this marker via the IsMarkedSecret helper to handle sensitive fields specially.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
@@ -28,11 +28,22 @@ import { z } from 'zod/v4';
|
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
export declare function Secret<T extends z.ZodTypeAny>(schema: T): T;
|
|
31
|
+
/**
|
|
32
|
+
* Generator function that traverses a Zod schema chain to its base type.
|
|
33
|
+
*
|
|
34
|
+
* Yields each schema in the unwrap chain, starting with the input schema.
|
|
35
|
+
* Handles both .unwrap() method (for schemas that support it) and .def.innerType fallback.
|
|
36
|
+
*
|
|
37
|
+
* @param schema - The Zod schema to traverse
|
|
38
|
+
* @yields Each schema in the chain from outermost to innermost
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export declare function traverseSchemaToBase(schema: z.ZodTypeAny): Generator<z.ZodTypeAny>;
|
|
31
42
|
/**
|
|
32
43
|
* Internal helper function that traverses the Zod schema metadata chain
|
|
33
44
|
* to determine if a schema is marked as secret.
|
|
34
45
|
*
|
|
35
|
-
* Walks through the
|
|
46
|
+
* Walks through the unwrap chain of wrapper schemas (e.g., ZodDefault,
|
|
36
47
|
* ZodOptional) and checks each level's metadata in the global registry.
|
|
37
48
|
*
|
|
38
49
|
* @param schema - The Zod schema to check for secret metadata
|
package/dist/secret.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAM3D;AAED;;;;;;;;;GASG;AACH,wBAAiB,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAkBnF;AAED;;;;;;;;;;GAUG;AACH,iBAAS,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,OAAO,CAgBrD;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/secret.js
CHANGED
|
@@ -12,7 +12,7 @@ import { z } from 'zod/v4';
|
|
|
12
12
|
*
|
|
13
13
|
* @remarks
|
|
14
14
|
* The inferred TypeScript type is unchanged and will not affect type inference
|
|
15
|
-
* for values validated by this schema.
|
|
15
|
+
* for values validated by this schema. RegisterConfigSchema automatically detects
|
|
16
16
|
* this marker via the IsMarkedSecret helper to handle sensitive fields specially.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
@@ -29,13 +29,41 @@ import { z } from 'zod/v4';
|
|
|
29
29
|
*/
|
|
30
30
|
export function Secret(schema) {
|
|
31
31
|
const existingMeta = z.globalRegistry.get(schema) ?? {};
|
|
32
|
+
if (existingMeta.secret === true) {
|
|
33
|
+
return schema; // Already marked as secret, no-op
|
|
34
|
+
}
|
|
32
35
|
return schema.meta({ ...existingMeta, secret: true });
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Generator function that traverses a Zod schema chain to its base type.
|
|
39
|
+
*
|
|
40
|
+
* Yields each schema in the unwrap chain, starting with the input schema.
|
|
41
|
+
* Handles both .unwrap() method (for schemas that support it) and .def.innerType fallback.
|
|
42
|
+
*
|
|
43
|
+
* @param schema - The Zod schema to traverse
|
|
44
|
+
* @yields Each schema in the chain from outermost to innermost
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export function* traverseSchemaToBase(schema) {
|
|
48
|
+
let current = schema;
|
|
49
|
+
while (current != null) {
|
|
50
|
+
yield current;
|
|
51
|
+
// Traverse to the next level via unwrap or .def.innerType (present in wrapper schemas)
|
|
52
|
+
const unwrapFn = current.unwrap;
|
|
53
|
+
if (typeof unwrapFn === 'function') {
|
|
54
|
+
current = unwrapFn.call(current);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const innerType = current.def?.innerType;
|
|
58
|
+
current = innerType;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
34
62
|
/**
|
|
35
63
|
* Internal helper function that traverses the Zod schema metadata chain
|
|
36
64
|
* to determine if a schema is marked as secret.
|
|
37
65
|
*
|
|
38
|
-
* Walks through the
|
|
66
|
+
* Walks through the unwrap chain of wrapper schemas (e.g., ZodDefault,
|
|
39
67
|
* ZodOptional) and checks each level's metadata in the global registry.
|
|
40
68
|
*
|
|
41
69
|
* @param schema - The Zod schema to check for secret metadata
|
|
@@ -43,8 +71,7 @@ export function Secret(schema) {
|
|
|
43
71
|
* @internal
|
|
44
72
|
*/
|
|
45
73
|
function IsMarkedSecret(schema) {
|
|
46
|
-
|
|
47
|
-
while (current != null) {
|
|
74
|
+
for (const current of traverseSchemaToBase(schema)) {
|
|
48
75
|
try {
|
|
49
76
|
const meta = z.globalRegistry.get(current);
|
|
50
77
|
if (meta?.secret === true) {
|
|
@@ -56,8 +83,6 @@ function IsMarkedSecret(schema) {
|
|
|
56
83
|
// Treat as non-secret and stop traversal.
|
|
57
84
|
break;
|
|
58
85
|
}
|
|
59
|
-
// Traverse to the next level via innerType (present in wrapper schemas)
|
|
60
|
-
current = current._def?.innerType;
|
|
61
86
|
}
|
|
62
87
|
return false;
|
|
63
88
|
}
|
package/dist/secret.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,MAAM,CAAyB,MAAS;IACvD,MAAM,YAAY,GAAG,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAM,CAAC;AAC5D,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,MAAM,CAAyB,MAAS;IACvD,MAAM,YAAY,GAAG,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,IAAK,YAAqC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,CAAC,kCAAkC;IAClD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAM,CAAC;AAC5D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,SAAS,CAAC,CAAC,oBAAoB,CAAC,MAAoB;IACzD,IAAI,OAAO,GAA6B,MAAM,CAAC;IAE/C,OAAO,OAAO,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,CAAC;QAEd,uFAAuF;QACvF,MAAM,QAAQ,GAAI,OAA2C,CAAC,MAAM,CAAC;QACrE,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACpC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAiB,CAAC;QAClD,CAAC;aACI,CAAC;YACL,MAAM,SAAS,GAAI,OAA6C,CAAC,GAAG,EAAE,SAEzD,CAAC;YACd,OAAO,GAAG,SAAS,CAAC;QACrB,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,cAAc,CAAC,MAAoB;IAC3C,KAAK,MAAM,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC3B,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QACD,MAAM,CAAC;YACN,8EAA8E;YAC9E,0CAA0C;YAC1C,MAAM;QACP,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,51 +1,65 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
2
|
+
"name": "@pawells/config",
|
|
3
|
+
"displayName": "Config",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"description": "Type-safe configuration management with environment variable loading and validation",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"config",
|
|
8
|
+
"configuration",
|
|
9
|
+
"schema",
|
|
10
|
+
"validation",
|
|
11
|
+
"zod",
|
|
12
|
+
"secrets",
|
|
13
|
+
"typescript",
|
|
14
|
+
"nodejs"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Phillip Aaron Wells",
|
|
19
|
+
"email": "69355326+PhillipAWells@users.noreply.github.com"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/PhillipAWells/config",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/PhillipAWells/config/issues"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/PhillipAWells/config.git",
|
|
28
|
+
"directory": "packages/config"
|
|
29
|
+
},
|
|
30
|
+
"funding": {
|
|
31
|
+
"type": "github",
|
|
32
|
+
"url": "https://github.com/sponsors/PhillipAWells"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22.0.0"
|
|
36
|
+
},
|
|
37
|
+
"type": "module",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"exports": {
|
|
40
|
+
"./package.json": "./package.json",
|
|
41
|
+
".": {
|
|
42
|
+
"local": "./src/index.ts",
|
|
43
|
+
"types": "./dist/index.d.ts",
|
|
44
|
+
"import": "./dist/index.js",
|
|
45
|
+
"default": "./dist/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist",
|
|
50
|
+
"!**/*.tsbuildinfo",
|
|
51
|
+
"LICENSE"
|
|
52
|
+
],
|
|
53
|
+
"sideEffects": false,
|
|
54
|
+
"scripts": {
|
|
55
|
+
"test:coverage": "yarn nx test config -- --coverage"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@pawells/typescript-common": "^3.0.5",
|
|
62
|
+
"tslib": "^2.8.1",
|
|
63
|
+
"zod": "^4.4.3"
|
|
64
|
+
}
|
|
51
65
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
[Unreleased]: https://github.com/PhillipAWells/common/compare/v2.3.0...HEAD
|
|
11
|
-
|
|
12
|
-
## [2.3.0] - 2026-06-01
|
|
13
|
-
|
|
14
|
-
### Added
|
|
15
|
-
|
|
16
|
-
- **Secret** — `Secret<T>` wrapper type for marking config values as sensitive; `IsSecret()` type guard for runtime detection; `GetSecretKeys()` for retrieving all secret field names from a config object; `Redact()` for producing a copy of a config with all secret values masked
|
|
17
|
-
- **ConfigManager.GenerateEnv** — new method for serializing a registered config to `.env` file format, with options to target specific keys and to unmask secret values
|
|
18
|
-
|
|
19
|
-
[2.3.0]: https://github.com/PhillipAWells/common/releases/tag/v2.3.0
|