@meltstudio/config-loader 3.3.0 → 3.5.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 +95 -0
- package/dist/index.d.ts +65 -7
- package/dist/index.js +116 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,8 @@ No separate interface to maintain. No `as` casts. The types flow from the schema
|
|
|
61
61
|
- **`.env` file support** — load environment variables from `.env` files with automatic line tracking
|
|
62
62
|
- **Nested objects and arrays** — deeply nested configs with full type safety
|
|
63
63
|
- **Structured errors** — typed `ConfigLoadError` with per-field error details and warnings
|
|
64
|
+
- **Enum constraints** — restrict values to a fixed set with `oneOf`, with full type narrowing
|
|
65
|
+
- **Sensitive fields** — mark fields with `sensitive: true` to auto-mask in `printConfig()` and `maskSecrets()`
|
|
64
66
|
- **Schema validation** — optional per-field validation via [Standard Schema](https://github.com/standard-schema/standard-schema) (Zod, Valibot, ArkType, or custom)
|
|
65
67
|
- **Strict mode** — promote warnings to errors for production safety
|
|
66
68
|
- **Default values** — static or computed (via functions)
|
|
@@ -253,6 +255,97 @@ c.array({
|
|
|
253
255
|
}); // { name: string; age: number }[]
|
|
254
256
|
```
|
|
255
257
|
|
|
258
|
+
## Enum Constraints (`oneOf`)
|
|
259
|
+
|
|
260
|
+
Use `oneOf` to restrict a field to a fixed set of allowed values. The check runs after type coercion and before any `validate` schema:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const config = c
|
|
264
|
+
.schema({
|
|
265
|
+
env: c.string({
|
|
266
|
+
env: "NODE_ENV",
|
|
267
|
+
defaultValue: "development",
|
|
268
|
+
oneOf: ["development", "staging", "production"],
|
|
269
|
+
}),
|
|
270
|
+
logLevel: c.number({
|
|
271
|
+
env: "LOG_LEVEL",
|
|
272
|
+
defaultValue: 1,
|
|
273
|
+
oneOf: [0, 1, 2, 3],
|
|
274
|
+
}),
|
|
275
|
+
})
|
|
276
|
+
.load({ env: true, args: false });
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
If a value is not in the allowed set, a `ConfigLoadError` is thrown with `kind: "validation"`.
|
|
280
|
+
|
|
281
|
+
### Type Narrowing
|
|
282
|
+
|
|
283
|
+
When `oneOf` is provided, the inferred type is automatically narrowed to the union of the allowed values:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
const config = c
|
|
287
|
+
.schema({
|
|
288
|
+
env: c.string({ oneOf: ["dev", "staging", "prod"] }),
|
|
289
|
+
})
|
|
290
|
+
.load({ env: false, args: false });
|
|
291
|
+
|
|
292
|
+
// config.env is typed as "dev" | "staging" | "prod", not string
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
When used with `cli: true`, the `--help` output automatically lists the allowed values.
|
|
296
|
+
|
|
297
|
+
## Sensitive Fields
|
|
298
|
+
|
|
299
|
+
Mark fields as `sensitive: true` to prevent their values from being exposed in logs or debug output:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const schema = {
|
|
303
|
+
host: c.string({ defaultValue: "localhost" }),
|
|
304
|
+
apiKey: c.string({ env: "API_KEY", sensitive: true }),
|
|
305
|
+
db: c.object({
|
|
306
|
+
item: {
|
|
307
|
+
host: c.string({ defaultValue: "db.local" }),
|
|
308
|
+
password: c.string({ env: "DB_PASS", sensitive: true }),
|
|
309
|
+
},
|
|
310
|
+
}),
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const config = c.schema(schema).load({ env: true, args: false });
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Sensitive values load normally — `config.apiKey` returns the real value. The flag only affects masking utilities.
|
|
317
|
+
|
|
318
|
+
### `printConfig()` auto-masking
|
|
319
|
+
|
|
320
|
+
`printConfig()` automatically masks sensitive fields:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const result = c.schema(schema).loadExtended({ env: true, args: false });
|
|
324
|
+
printConfig(result);
|
|
325
|
+
// apiKey shows "***" instead of the real value
|
|
326
|
+
// db.password shows "***" instead of the real value
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### `maskSecrets()`
|
|
330
|
+
|
|
331
|
+
Use `maskSecrets()` to create a safe-to-log copy of your config:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import c, { maskSecrets } from "@meltstudio/config-loader";
|
|
335
|
+
|
|
336
|
+
// With a plain config from load()
|
|
337
|
+
const config = c.schema(schema).load({ env: true, args: false });
|
|
338
|
+
console.log(maskSecrets(config, schema));
|
|
339
|
+
// { host: "localhost", apiKey: "***", db: { host: "db.local", password: "***" } }
|
|
340
|
+
|
|
341
|
+
// With an extended result from loadExtended()
|
|
342
|
+
const result = c.schema(schema).loadExtended({ env: true, args: false });
|
|
343
|
+
const masked = maskSecrets(result);
|
|
344
|
+
// masked.data contains ConfigNodes with "***" for sensitive values
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
The original config object is never mutated — `maskSecrets()` always returns a new copy.
|
|
348
|
+
|
|
256
349
|
## Validation
|
|
257
350
|
|
|
258
351
|
Add per-field validation using the `validate` option. config-loader accepts any [Standard Schema v1](https://github.com/standard-schema/standard-schema) implementation — including **Zod**, **Valibot**, and **ArkType** — or a custom validator.
|
|
@@ -471,6 +564,8 @@ import c, {
|
|
|
471
564
|
ConfigNodeArray, // Class representing an array of ConfigNode values
|
|
472
565
|
type RecursivePartial, // Deep partial utility used by the defaults option
|
|
473
566
|
type StandardSchemaV1, // Standard Schema v1 interface for validators
|
|
567
|
+
maskSecrets, // Create a safe-to-log copy with sensitive values masked
|
|
568
|
+
printConfig, // Format loadExtended() result as a readable table
|
|
474
569
|
} from "@meltstudio/config-loader";
|
|
475
570
|
```
|
|
476
571
|
|
package/dist/index.d.ts
CHANGED
|
@@ -60,7 +60,9 @@ interface OptionClassParams<T extends OptionKind> {
|
|
|
60
60
|
env: string | null;
|
|
61
61
|
cli: boolean;
|
|
62
62
|
help: string;
|
|
63
|
+
sensitive?: boolean;
|
|
63
64
|
defaultValue?: TypedDefaultValue<T>;
|
|
65
|
+
oneOf?: ReadonlyArray<string | number | boolean>;
|
|
64
66
|
validate?: StandardSchemaV1;
|
|
65
67
|
}
|
|
66
68
|
declare class OptionBase<T extends OptionKind = OptionKind> {
|
|
@@ -81,6 +83,7 @@ declare class OptionBase<T extends OptionKind = OptionKind> {
|
|
|
81
83
|
} | null;
|
|
82
84
|
}, envFileResults?: EnvFileResult[], errors?: OptionErrors): ConfigNode | null;
|
|
83
85
|
private resolveValue;
|
|
86
|
+
private runOneOfCheck;
|
|
84
87
|
private runValidation;
|
|
85
88
|
private resolveFromFileData;
|
|
86
89
|
checkType(val: Value, path: Path, sourceOfVal: string, errors?: OptionErrors): Value;
|
|
@@ -98,10 +101,11 @@ declare class ConfigNode {
|
|
|
98
101
|
argName: string | null;
|
|
99
102
|
line: number | null;
|
|
100
103
|
column: number | null;
|
|
101
|
-
|
|
104
|
+
sensitive: boolean;
|
|
105
|
+
constructor(value: Value | ArrayValue, path: string, sourceType: SourceTypes, file: string | null, variableName: string | null, argName: string | null, line?: number | null, column?: number | null, sensitive?: boolean);
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
declare class PrimitiveOption<T extends PrimitiveKind = PrimitiveKind
|
|
108
|
+
declare class PrimitiveOption<T extends PrimitiveKind = PrimitiveKind, Narrowed = TypeOfPrimitiveKind<T>> extends OptionBase<T> {
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
type NodeTree = {
|
|
@@ -140,7 +144,7 @@ type TypeOfPrimitiveKind<T extends PrimitiveKind> = T extends "boolean" ? boolea
|
|
|
140
144
|
/** Recursively infers the plain TypeScript type from a schema definition. Maps option nodes to their resolved value types. */
|
|
141
145
|
type SchemaValue<T extends OptionBase | Node> = T extends OptionBase ? T extends ArrayOption<OptionTypes> ? SchemaValue<T["item"]>[] : T extends ObjectOption<infer R> ? {
|
|
142
146
|
[K in keyof R]: SchemaValue<R[K]>;
|
|
143
|
-
} : T extends PrimitiveOption<infer
|
|
147
|
+
} : T extends PrimitiveOption<infer _R, infer Narrowed> ? Narrowed : never : T extends Node ? {
|
|
144
148
|
[K in keyof T]: SchemaValue<T[K]>;
|
|
145
149
|
} : never;
|
|
146
150
|
type Path = Array<string | number>;
|
|
@@ -223,6 +227,24 @@ declare class SettingsBuilder<T extends Node> {
|
|
|
223
227
|
loadExtended(sources: SettingsSources<SchemaValue<T>>): ExtendedResult;
|
|
224
228
|
}
|
|
225
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Masks sensitive values in an `ExtendedResult` from `loadExtended()`.
|
|
232
|
+
* Fields marked `sensitive: true` have their values replaced with `"***"`.
|
|
233
|
+
*
|
|
234
|
+
* @param result - The `ExtendedResult` returned by `loadExtended()`.
|
|
235
|
+
* @returns A new `ExtendedResult` with sensitive values masked.
|
|
236
|
+
*/
|
|
237
|
+
declare function maskSecrets(result: ExtendedResult): ExtendedResult;
|
|
238
|
+
/**
|
|
239
|
+
* Masks sensitive values in a plain config object from `load()`.
|
|
240
|
+
* Fields marked `sensitive: true` in the schema have their values replaced with `"***"`.
|
|
241
|
+
*
|
|
242
|
+
* @param config - The plain config object returned by `load()`.
|
|
243
|
+
* @param schema - The schema definition used to identify sensitive fields.
|
|
244
|
+
* @returns A new object with sensitive values masked.
|
|
245
|
+
*/
|
|
246
|
+
declare function maskSecrets<T extends Record<string, unknown>>(config: T, schema: Node): T;
|
|
247
|
+
|
|
226
248
|
declare class ConfigNodeArray {
|
|
227
249
|
arrayValues: ConfigNode[];
|
|
228
250
|
constructor(arrayValues: ConfigNode[]);
|
|
@@ -260,6 +282,10 @@ interface OptionPropsArgs<T> {
|
|
|
260
282
|
defaultValue?: T | (() => T);
|
|
261
283
|
/** Help text shown in CLI `--help` output. */
|
|
262
284
|
help?: string;
|
|
285
|
+
/** Mark this field as sensitive. Sensitive values are masked by `printConfig()` and `maskSecrets()`. */
|
|
286
|
+
sensitive?: boolean;
|
|
287
|
+
/** Restrict the value to a fixed set of allowed values. Checked after type coercion, before `validate`. */
|
|
288
|
+
oneOf?: readonly T[];
|
|
263
289
|
/** Standard Schema validator run after type coercion. Accepts Zod, Valibot, ArkType, or any Standard Schema v1 implementation. */
|
|
264
290
|
validate?: StandardSchemaV1;
|
|
265
291
|
}
|
|
@@ -283,6 +309,38 @@ interface ObjectOptionPropsArgs<T extends Node> {
|
|
|
283
309
|
/** Standard Schema validator run on the resolved object. Accepts Zod, Valibot, ArkType, or any Standard Schema v1 implementation. */
|
|
284
310
|
validate?: StandardSchemaV1;
|
|
285
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Creates a string configuration option.
|
|
314
|
+
* @param opts - Option configuration (env, cli, required, defaultValue, help, oneOf).
|
|
315
|
+
* @returns A `PrimitiveOption<"string">` for use in a schema.
|
|
316
|
+
* @example
|
|
317
|
+
* c.string({ env: "HOST", defaultValue: "localhost" })
|
|
318
|
+
* c.string({ env: "NODE_ENV", oneOf: ["development", "staging", "production"] })
|
|
319
|
+
*/
|
|
320
|
+
declare function string<const V extends readonly string[]>(opts: OptionPropsArgs<string> & {
|
|
321
|
+
oneOf: V;
|
|
322
|
+
}): PrimitiveOption<"string", V[number]>;
|
|
323
|
+
declare function string(opts?: OptionPropsArgs<string>): PrimitiveOption<"string">;
|
|
324
|
+
/**
|
|
325
|
+
* Creates a number configuration option. String values from env/CLI are coerced to numbers.
|
|
326
|
+
* @param opts - Option configuration (env, cli, required, defaultValue, help, oneOf).
|
|
327
|
+
* @returns A `PrimitiveOption<"number">` for use in a schema.
|
|
328
|
+
* @example
|
|
329
|
+
* c.number({ env: "PORT", defaultValue: 3000 })
|
|
330
|
+
* c.number({ env: "LOG_LEVEL", oneOf: [0, 1, 2, 3] })
|
|
331
|
+
*/
|
|
332
|
+
declare function number<const V extends readonly number[]>(opts: OptionPropsArgs<number> & {
|
|
333
|
+
oneOf: V;
|
|
334
|
+
}): PrimitiveOption<"number", V[number]>;
|
|
335
|
+
declare function number(opts?: OptionPropsArgs<number>): PrimitiveOption<"number">;
|
|
336
|
+
/**
|
|
337
|
+
* Creates a boolean configuration option. String values `"true"`/`"false"` are coerced.
|
|
338
|
+
* @param opts - Option configuration (env, cli, required, defaultValue, help).
|
|
339
|
+
* @returns A `PrimitiveOption<"boolean">` for use in a schema.
|
|
340
|
+
* @example
|
|
341
|
+
* c.bool({ env: "DEBUG", defaultValue: false })
|
|
342
|
+
*/
|
|
343
|
+
declare function bool(opts?: OptionPropsArgs<boolean>): PrimitiveOption<"boolean">;
|
|
286
344
|
/**
|
|
287
345
|
* Config-loader entry point. Provides factory functions to define a typed configuration schema.
|
|
288
346
|
*
|
|
@@ -297,12 +355,12 @@ interface ObjectOptionPropsArgs<T extends Node> {
|
|
|
297
355
|
* ```
|
|
298
356
|
*/
|
|
299
357
|
declare const option: {
|
|
300
|
-
string:
|
|
301
|
-
number:
|
|
302
|
-
bool:
|
|
358
|
+
string: typeof string;
|
|
359
|
+
number: typeof number;
|
|
360
|
+
bool: typeof bool;
|
|
303
361
|
array: <T extends OptionTypes>(opts: ArrayOptionPropsArgs<T>) => ArrayOption<T>;
|
|
304
362
|
object: <T extends Node>(opts: ObjectOptionPropsArgs<T>) => ObjectOption<T>;
|
|
305
363
|
schema: <T extends Node>(theSchema: T) => SettingsBuilder<T>;
|
|
306
364
|
};
|
|
307
365
|
|
|
308
|
-
export { type ConfigErrorEntry, ConfigFileError, ConfigLoadError, ConfigNode, ConfigNodeArray, type ExtendedResult, type NodeTree, type RecursivePartial, type SchemaValue, type SettingsSources, type StandardSchemaV1, option as default, printConfig };
|
|
366
|
+
export { type ConfigErrorEntry, ConfigFileError, ConfigLoadError, ConfigNode, ConfigNodeArray, type ExtendedResult, type NodeTree, type RecursivePartial, type SchemaValue, type SettingsSources, type StandardSchemaV1, option as default, maskSecrets, printConfig };
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
ConfigNode: () => configNode_default,
|
|
36
36
|
ConfigNodeArray: () => configNodeArray_default,
|
|
37
37
|
default: () => index_default,
|
|
38
|
+
maskSecrets: () => maskSecrets,
|
|
38
39
|
printConfig: () => printConfig
|
|
39
40
|
});
|
|
40
41
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -81,7 +82,8 @@ var ConfigNode = class {
|
|
|
81
82
|
argName;
|
|
82
83
|
line;
|
|
83
84
|
column;
|
|
84
|
-
|
|
85
|
+
sensitive;
|
|
86
|
+
constructor(value, path2, sourceType, file, variableName, argName, line = null, column = null, sensitive = false) {
|
|
85
87
|
this.value = value;
|
|
86
88
|
this.path = path2;
|
|
87
89
|
this.sourceType = sourceType;
|
|
@@ -90,6 +92,7 @@ var ConfigNode = class {
|
|
|
90
92
|
this.argName = argName;
|
|
91
93
|
this.line = line;
|
|
92
94
|
this.column = column;
|
|
95
|
+
this.sensitive = sensitive;
|
|
93
96
|
}
|
|
94
97
|
};
|
|
95
98
|
var configNode_default = ConfigNode;
|
|
@@ -292,6 +295,13 @@ var OptionBase = class {
|
|
|
292
295
|
envFileResults,
|
|
293
296
|
errors
|
|
294
297
|
);
|
|
298
|
+
if (resolved && this.params.sensitive) {
|
|
299
|
+
resolved.sensitive = true;
|
|
300
|
+
}
|
|
301
|
+
if (resolved && this.params.oneOf) {
|
|
302
|
+
const passed = this.runOneOfCheck(resolved, path2, errors);
|
|
303
|
+
if (!passed) return resolved;
|
|
304
|
+
}
|
|
295
305
|
if (resolved && this.params.validate) {
|
|
296
306
|
this.runValidation(resolved, path2, errors);
|
|
297
307
|
}
|
|
@@ -455,6 +465,27 @@ var OptionBase = class {
|
|
|
455
465
|
}
|
|
456
466
|
return null;
|
|
457
467
|
}
|
|
468
|
+
runOneOfCheck(node, path2, errors) {
|
|
469
|
+
const allowed = this.params.oneOf;
|
|
470
|
+
if (!allowed) return true;
|
|
471
|
+
const value = node.value;
|
|
472
|
+
if (valueIsInvalid(value)) return true;
|
|
473
|
+
if (!allowed.includes(value)) {
|
|
474
|
+
const ident = path2.join(".");
|
|
475
|
+
const source = node.file ?? node.variableName ?? node.argName ?? node.sourceType;
|
|
476
|
+
const allowedStr = allowed.map((v) => `'${String(v)}'`).join(", ");
|
|
477
|
+
errors?.errors.push({
|
|
478
|
+
message: `Value '${typeof value === "object" ? JSON.stringify(value) : String(value)}' for '${ident}' is not one of: ${allowedStr}.`,
|
|
479
|
+
path: ident,
|
|
480
|
+
source,
|
|
481
|
+
kind: "validation",
|
|
482
|
+
line: node.line ?? void 0,
|
|
483
|
+
column: node.column ?? void 0
|
|
484
|
+
});
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
return true;
|
|
488
|
+
}
|
|
458
489
|
runValidation(node, path2, errors) {
|
|
459
490
|
const validator = this.params.validate;
|
|
460
491
|
if (!validator) return;
|
|
@@ -1034,7 +1065,12 @@ var Settings = class {
|
|
|
1034
1065
|
addArg(node, path2 = []) {
|
|
1035
1066
|
if (node.params.cli) {
|
|
1036
1067
|
const ident = path2.join(".");
|
|
1037
|
-
|
|
1068
|
+
let help = node.params.help;
|
|
1069
|
+
if (node.params.oneOf) {
|
|
1070
|
+
const allowed = node.params.oneOf.map(String).join(", ");
|
|
1071
|
+
help = help ? `${help} (one of: ${allowed})` : `one of: ${allowed}`;
|
|
1072
|
+
}
|
|
1073
|
+
this.program.option(`--${ident} <value>`, help);
|
|
1038
1074
|
}
|
|
1039
1075
|
}
|
|
1040
1076
|
getValuesFromTree(node) {
|
|
@@ -1097,6 +1133,76 @@ var SettingsBuilder = class {
|
|
|
1097
1133
|
}
|
|
1098
1134
|
};
|
|
1099
1135
|
|
|
1136
|
+
// src/maskSecrets.ts
|
|
1137
|
+
var MASK = "***";
|
|
1138
|
+
function maskNodeTree(tree) {
|
|
1139
|
+
const result = {};
|
|
1140
|
+
for (const [key, entry] of Object.entries(tree)) {
|
|
1141
|
+
if (entry instanceof configNode_default) {
|
|
1142
|
+
if (entry.sensitive) {
|
|
1143
|
+
const masked = new configNode_default(
|
|
1144
|
+
MASK,
|
|
1145
|
+
entry.path,
|
|
1146
|
+
entry.sourceType,
|
|
1147
|
+
entry.file,
|
|
1148
|
+
entry.variableName,
|
|
1149
|
+
entry.argName,
|
|
1150
|
+
entry.line,
|
|
1151
|
+
entry.column,
|
|
1152
|
+
entry.sensitive
|
|
1153
|
+
);
|
|
1154
|
+
if (entry.value instanceof configNodeArray_default) {
|
|
1155
|
+
masked.value = entry.value;
|
|
1156
|
+
}
|
|
1157
|
+
result[key] = masked;
|
|
1158
|
+
} else {
|
|
1159
|
+
result[key] = entry;
|
|
1160
|
+
}
|
|
1161
|
+
} else {
|
|
1162
|
+
result[key] = maskNodeTree(entry);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return result;
|
|
1166
|
+
}
|
|
1167
|
+
function maskPlainObject(obj, schema2) {
|
|
1168
|
+
const result = {};
|
|
1169
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1170
|
+
const schemaNode = schema2[key];
|
|
1171
|
+
if (!schemaNode) {
|
|
1172
|
+
result[key] = value;
|
|
1173
|
+
continue;
|
|
1174
|
+
}
|
|
1175
|
+
if (schemaNode instanceof ObjectOption) {
|
|
1176
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
1177
|
+
result[key] = maskPlainObject(
|
|
1178
|
+
value,
|
|
1179
|
+
schemaNode.item
|
|
1180
|
+
);
|
|
1181
|
+
} else {
|
|
1182
|
+
result[key] = value;
|
|
1183
|
+
}
|
|
1184
|
+
} else if (schemaNode instanceof OptionBase) {
|
|
1185
|
+
result[key] = schemaNode.params.sensitive ? MASK : value;
|
|
1186
|
+
} else {
|
|
1187
|
+
result[key] = value;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return result;
|
|
1191
|
+
}
|
|
1192
|
+
function maskSecrets(resultOrConfig, schema2) {
|
|
1193
|
+
if ("data" in resultOrConfig && "warnings" in resultOrConfig && !schema2) {
|
|
1194
|
+
const extended = resultOrConfig;
|
|
1195
|
+
return {
|
|
1196
|
+
data: maskNodeTree(extended.data),
|
|
1197
|
+
warnings: [...extended.warnings]
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
if (schema2) {
|
|
1201
|
+
return maskPlainObject(resultOrConfig, schema2);
|
|
1202
|
+
}
|
|
1203
|
+
return resultOrConfig;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1100
1206
|
// src/printConfig.ts
|
|
1101
1207
|
function truncate(str, max) {
|
|
1102
1208
|
if (str.length <= max) return str;
|
|
@@ -1153,7 +1259,7 @@ function flattenTree(tree, prefix = "") {
|
|
|
1153
1259
|
} else {
|
|
1154
1260
|
rows.push({
|
|
1155
1261
|
path: path2,
|
|
1156
|
-
value: formatValue(entry.value),
|
|
1262
|
+
value: entry.sensitive ? "***" : formatValue(entry.value),
|
|
1157
1263
|
source: entry.sourceType,
|
|
1158
1264
|
detail: formatDetail(entry)
|
|
1159
1265
|
});
|
|
@@ -1225,27 +1331,27 @@ var DEFAULTS = {
|
|
|
1225
1331
|
cli: false,
|
|
1226
1332
|
help: ""
|
|
1227
1333
|
};
|
|
1228
|
-
|
|
1334
|
+
function string(opts) {
|
|
1229
1335
|
return new PrimitiveOption({
|
|
1230
1336
|
kind: "string",
|
|
1231
1337
|
...DEFAULTS,
|
|
1232
1338
|
...opts
|
|
1233
1339
|
});
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1340
|
+
}
|
|
1341
|
+
function number(opts) {
|
|
1236
1342
|
return new PrimitiveOption({
|
|
1237
1343
|
kind: "number",
|
|
1238
1344
|
...DEFAULTS,
|
|
1239
1345
|
...opts
|
|
1240
1346
|
});
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1347
|
+
}
|
|
1348
|
+
function bool(opts) {
|
|
1243
1349
|
return new PrimitiveOption({
|
|
1244
1350
|
kind: "boolean",
|
|
1245
1351
|
...DEFAULTS,
|
|
1246
1352
|
...opts
|
|
1247
1353
|
});
|
|
1248
|
-
}
|
|
1354
|
+
}
|
|
1249
1355
|
var array = (opts) => {
|
|
1250
1356
|
return new ArrayOption({
|
|
1251
1357
|
...DEFAULTS,
|
|
@@ -1276,5 +1382,6 @@ var index_default = option;
|
|
|
1276
1382
|
ConfigLoadError,
|
|
1277
1383
|
ConfigNode,
|
|
1278
1384
|
ConfigNodeArray,
|
|
1385
|
+
maskSecrets,
|
|
1279
1386
|
printConfig
|
|
1280
1387
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meltstudio/config-loader",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Type-safe configuration loader with full TypeScript inference. Load from YAML, JSON, .env, environment variables, and CLI args.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|