Loading an object config value fails if format isn't specified explicitly
I'm not sure what you want to do about this one, really. Most of the time, the type of a value is inferred from the default value if it's not specified. If that type is an object, e.g.:
var conf = convict({
foo: {
default: { foo: 'bar' }
}
});
and you try to load some data...
conf.load({
foo: { baz: 'quux' }
});
... it succeeds. But if that data contains deeper properties...
conf.load({
foo: {
bar: { baz: 'quux' }
}
});
... you get an error (cannot access property of undefined)
If you change the schema to specify format: Object, the error does not occur.
The weird way convict mixes configuration schema and data may mean that there's no clean solution, but if the alternative is "fail with a difficult to comprehend error", it seems likely that simply inferring the type of an object property to be Object will make the error go away as well as make convict more useful.
Full failing test case:
'use strict';
var convict = require('convict');
var conf = convict({
foo: {
default: { some: 'data' }
}
});
conf.load({
foo: {
bar: {
baz: 'quux'
}
}
});
Thanks for reporting this! I'll investigate when I can.
Same problem is exposed when trying to define custom type accepting object value
convict.addFormat({
name: 'custom',
validate: (val) => {
console.error('validate called', val);
},
coerce: (val) => {
console.error('coerce called', val);
return val;
}
});
const conf = convict({
foo: {
format: 'custom',
default: {},
}
});
conf.load({
foo: {
bar: { baz: 'quux' }
}
});
Any updates? I have the same problem as @Xerkus
Not reproductible anymore, your code don't throw an error.
code
var convict = require('convict');
var conf = convict({
foo: {
default: { some: 'data' }
}
});
conf.load({
foo: {
bar: {
baz: 'quux'
}
}
});
conf.validate();
convict.addFormat({
name: 'custom',
validate: (val) => {
console.error('validate called', val);
},
coerce: (val) => {
console.error('coerce called', val);
return val;
}
});
const conf = convict({
foo: {
format: 'custom',
default: {},
}
});
conf.load({
foo: {
bar: { baz: 'quux' }
}
});
conf.validate();
I still get an error when using a function as the format:
import convict from "convict";
interface Foo {
a: { b: number };
}
export function foo(val: any): asserts val is Foo {
if (typeof val?.a?.b !== "number") {
throw new Error();
}
}
const config = convict({
foo: {
format: foo,
default: {
a: { b: 1 },
},
},
});
config.load({ foo: { a: { b: 2 } } });
const f = config.get("foo");
console.dir(f);