Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading an object config value fails if format isn't specified explicitly #136

Open
myndzi opened this issue Mar 23, 2016 · 5 comments
Open

Comments

@myndzi
Copy link
Contributor

myndzi commented Mar 23, 2016

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'
    }
  }
});
@madarche
Copy link
Collaborator

Thanks for reporting this! I'll investigate when I can.

@Xerkus
Copy link

Xerkus commented Sep 23, 2016

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' }
        }
    });

@yurtaev
Copy link

yurtaev commented Oct 31, 2017

Any updates? I have the same problem as @Xerkus

@A-312
Copy link
Contributor

A-312 commented Jan 6, 2020

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();

@awlayton
Copy link

awlayton commented May 14, 2021

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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants