node-convict icon indicating copy to clipboard operation
node-convict copied to clipboard

Loading duration from config file doesn't convert duration to ms

Open pdehaan opened this issue 10 years ago • 4 comments

Steps to reproduce:

  1. Copy/paste the following magic sauce as ./index.js:

    var convict = require('convict');
    
    var conf = convict({
    session: {
      format: 'duration',
      default: '8 seconds'
    }
    });
    
    // conf.loadFile('./config.json');
    conf.validate();
    
    console.log(conf.get('session'));
    
    setTimeout(function () {
    console.log('timeout called after %s milliseconds', conf.get('session'));
    }, conf.get('session'));
    
  2. Save and run. Output should look like:

    $ node index
    8000
    timeout called after 8000 milliseconds # <--- This will appear after ~8 seconds.
    
  3. Add a ./config.json file and paste in the following:

    {
    "session": "19 seconds"
    }
    
  4. Uncomment the // conf.loadFile('./config.json'); line in the ./index.js file.

  5. Save and run. Output should look like:

    $ node index
    19 seconds
    timeout called after 19 seconds milliseconds # <--- This is invoked immediately and says "19 seconds" instead of 19000.
    

Actual results:

timeout called after 19 seconds milliseconds

Expected results:

timeout called after 19000 milliseconds

pdehaan avatar Feb 12 '15 00:02 pdehaan

Not sure if I'm trying to use Convict incorrectly. I was hoping to simplify our configs to use "1 week" instead of having to convert those to milliseconds in the local.json files. But this seems to be returning the duration as a string (when loading from an external file) versus converting to milliseconds (like when it uses the default value from Convict).

pdehaan avatar Feb 12 '15 00:02 pdehaan

Can you reproduct your problem ? Because I can't. I tried :

var convict = require('convict');

var conf = convict({
session: {
  format: 'duration',
  default: '8 seconds'
}
});

conf.loadFile('./config.json');
conf.validate();

console.log(conf.get('session'));

setTimeout(function () {
console.log('timeout called after %s milliseconds', conf.get('session'));
}, 5);
{
"session": "19 seconds"
}
λ node server.js
19000
timeout called after 19000 milliseconds

A-312 avatar Dec 08 '19 14:12 A-312

Hi, I'm having the same problem, using convict and convict-format-with-moment version 6.0.0 (latest). If I write

{
    "session": 19000
}

it is loaded correctly; if I write

{
    "session": "19 seconds"
}

the coercion seems to do the conversion correctly, but then if I do conf.get('session'), I still get the '19 seconds' string.

@A-312 : when you do

setTimeout(function () {
    console.log('timeout called after %s milliseconds', conf.get('session'));
}, 5);

How many seconds it takes to print to console? And why did you put 5 instead of conf.get('session') in the last line?..

ocramot avatar Oct 27 '20 10:10 ocramot

PS: I found the workaround for my issue. I noticed that if I put a duration value in the root of the JSON, it is correctly converted. My issue was with a duration value in a item of an array. I was using the sample validate function that can be found here: https://github.com/mozilla/node-convict/tree/master/packages/convict#custom-format-for-array-items

For some reason, the array items, once validated, are not reported back to the parent JSON and they remain unchanged.

I solved by replacing these lines

for (source of sources) {
    convict(schema.children).load(source).validate();
}

with these

for (let i = 0; i < sources.length; i++) {
    sources[i] = convict(schema.children).load(sources[i]).validate().getProperties();
}

I don't know if this is the same problem as OP's, I'll leave this here if can be useful to anyone.

ocramot avatar Oct 27 '20 16:10 ocramot