Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

confit

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

confit - npm Package Compare versions

Comparing version 0.1.0 to 1.0.0

CONTRIBUTING.md

266

index.js

@@ -0,5 +1,19 @@

/*───────────────────────────────────────────────────────────────────────────*\
│ Copyright (C) 2014 eBay Software Foundation │
│ │
│ Licensed under the Apache License, Version 2.0 (the "License"); │
│ you may not use this file except in compliance with the License. │
│ You may obtain a copy of the License at │
│ │
│ http://www.apache.org/licenses/LICENSE-2.0 │
│ │
│ Unless required by applicable law or agreed to in writing, software │
│ distributed under the License is distributed on an "AS IS" BASIS, │
│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │
│ See the License for the specific language governing permissions and │
│ limitations under the License. │
\*───────────────────────────────────────────────────────────────────────────*/
'use strict';
var path = require('path');
var nconf = require('nconf');
var shush = require('shush');

@@ -9,110 +23,100 @@ var caller = require('caller');

var shortstop = require('shortstop');
var common = require('./lib/common');
var provider = require('./lib/provider');
var debug = require('debuglog')('confit');
var env = require('./lib/env');
var util = require('./lib/util');
/**
* Initializes environment convenience props in the provided nconf provider.
* @param config an nconf Provider.
* @returns {Object} the newly configured nconf Provider.
*/
function environment(nodeEnv) {
var data = {};
function config(store) {
return {
debug('NODE_ENV set to \'%s\'', nodeEnv);
get: function get(key) {
var obj;
// Normalize env and set convenience values.
Object.keys(env).forEach(function (current) {
var match;
if (thing.isString(key) && key.length) {
match = env[current].test(nodeEnv);
if (match) { nodeEnv = current; }
key = key.split(':');
obj = store;
data[current] = match;
});
while (obj && key.length) {
if (obj.constructor !== Object) {
// Do not allow traversal into complex types,
// such as Buffer, Date, etc. So, this type
// of key will fail: 'foo:mystring:length'
return undefined;
}
obj = obj[key.shift()];
}
debug('env:env set to \'%s\'', nodeEnv);
return obj;
// Set (or re-set) env:{nodeEnv} value in case
// NODE_ENV was not one of our predetermined env
// keys (so `config.get('env:blah')` will be true).
data[nodeEnv] = true;
data.env = nodeEnv;
return { env: data };
}
}
return undefined;
},
/**
* Creates a local nconf provider instance. NO GLOBAL!
* @returns {Object} an nconf provider
*/
function provider() {
var config;
set: function set(key, value) {
var obj, prop;
config = new nconf.Provider();
config.add('argv');
config.add('env');
if (thing.isString(key) && key.length) {
// Put override before memory to ensure env
// values are immutable.
config.overrides({
type: 'literal',
store: environment(config.get('NODE_ENV') || 'development')
});
key = key.split(':');
obj = store;
config.add('memory');
while (key.length - 1) {
prop = key.shift();
return config;
}
// Create new object for property, if nonexistent
if (!obj.hasOwnProperty(prop)) {
obj[prop] = {};
}
obj = obj[prop];
if (obj && obj.constructor !== Object) {
// Do not allow traversal into complex types,
// such as Buffer, Date, etc. So, this type
// of key will fail: 'foo:mystring:length'
return undefined;
}
}
/**
* Creates a file loader that uses the provided `basedir`.
* @param basedir the root directory against which file paths will be resolved.
* @returns {Function} the file loader implementation.
*/
function loader(basedir) {
return (obj[key.shift()] = value);
}
return function load(file) {
var name, config;
return undefined;
},
name = path.basename(file, path.extname(file));
config = path.join(basedir, file);
use: function use(obj) {
common.merge(obj, store);
}
return {
name: name,
data: shush(config)
};
};
}
/**
* Wraps the provided nconf Provider in a simpler convenience API.
* @param config an nconf Provider.
*/
function wrap(config) {
function builder(options) {
return {
get: function get(key) {
return config.get(key);
},
_store: {},
set: function set(key, value) {
// NOTE: There was discussion around potentially warning
// on attempts to set immutable values. The would require
// a minimum of one additional operation, which was deemed
// overkill for a small/unlikely scenrio. Can revisit.
config.set(key, value);
addOverride: function addOverride(file) {
file = common.isAbsolute(file) ? file : path.join(options.basedir, file);
common.merge(shush(file), this._store);
return this;
},
use: function use(obj) {
// Merge into memory store.
// This must be done b/c nconf applies things kind of backward.
// If we just used a literal store it would get added to the END
// so no values would be overridden. Additionally, only the memory
// store is writable at this point so all updates live there.
config.merge(obj);
create: function create(callback) {
var shorty;
shorty = shortstop.create();
Object.keys(options.protocols).forEach(function (protocol) {
shorty.use(protocol, options.protocols[protocol]);
});
shorty.resolve(this._store, function (err, data) {
if (err) {
callback(err);
return;
}
callback(null, config(data));
});
}

@@ -124,18 +128,31 @@

/**
* Main module entrypoint. Creates a confit config object using the provided
* options.
* @param options the configuration settings for this config instance.
* @param callback the function to which error or config object will be passed.
*/
module.exports = function confit(options, callback) {
var shorty, config, tasks, load;
function possibly(resolve, reject) {
return function maybe() {
try {
return resolve.apply(null, arguments);
} catch (err) {
reject(err);
}
};
}
// Normalize arguments
if (thing.isFunction(options)) {
callback = options;
options = undefined;
function resolve(file, store) {
return common.merge(shush(file), store);
}
function reject(err) {
if (err.code && err.code === 'MODULE_NOT_FOUND') {
debug('WARNING:', err.message);
return;
}
throw err;
}
// ... still normalizing
module.exports = function confit(options) {
var factory, margeFile, file;
// Normalize arguments
if (thing.isString(options)) {

@@ -149,56 +166,21 @@ options = { basedir: options };

options.basedir = options.basedir || path.dirname(caller());
options.protocols = options.protocols || {};
factory = builder(options);
common.merge(provider.argv(), factory._store);
common.merge(provider.env(), factory._store);
common.merge(provider.convenience(), factory._store);
// Configure shortstop using provided protocols
shorty = shortstop.create();
if (thing.isObject(options.protocols)) {
Object.keys(options.protocols).forEach(function (protocol) {
shorty.use(protocol, options.protocols[protocol]);
});
}
// Backdoor a couple files before we get going.
margeFile = possibly(resolve, reject);
// Create config provider and initialize basedir
// TODO: Add basedir to overrides so it's readonly?
config = provider();
config.set('basedir', options.basedir);
// File 1: The default config file.
file = path.join(options.basedir, options.defaults);
margeFile(file, factory._store);
// File 2: The env-specific config file.
file = path.join(options.basedir, factory._store.env.env + '.json');
margeFile(file, factory._store);
tasks = [];
load = loader(options.basedir);
// Load the env-specific config file as a literal
// datastore. Can't use `file` b/c we preprocess it.
tasks.push(function (done) {
var file = load(config.get('env:env') + '.json');
config.use(file.name, {
type: 'literal',
store: shorty.resolve(file.data)
});
done();
});
// Set defaults from `defaults` file.
tasks.push(function (done) {
var file = load(options.defaults);
config.defaults(shorty.resolve(file.data));
done();
});
util.each(tasks, function (err) {
// XXX: Force async until shortstop@1.0 is integrated.
// Only report unusual errors. MODULE_NOT_FOUND is an
// acceptable scenario b/c no files are truly requried.
if (thing.isObject(err) && err.code !== 'MODULE_NOT_FOUND') {
setImmediate(callback.bind(null, err));
return;
}
config = wrap(config);
setImmediate(callback.bind(null, null, config));
});
return factory;
};
{
"name": "confit",
"version": "0.1.0",
"version": "1.0.0",
"description": "Environment-aware configuration.",

@@ -16,3 +16,3 @@ "main": "index.js",

"type": "git",
"url": "git://github.com/totherik/confit.git"
"url": "git://github.com/krakenjs/confit.git"
},

@@ -25,5 +25,9 @@ "keywords": [

"author": "Erik Toth <totherik@gmail.com>",
"license": "MIT",
"licenses": [
{
"type": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
],
"readmeFilename": "README.md",
"gitHead": "4bc76f5804f42d55cacd5cdbc3661ad1c605b3ca",
"devDependencies": {

@@ -35,10 +39,9 @@ "tape": "~2.10.2",

"dependencies": {
"nconf": "~0.6.9",
"shortstop": "0.0.1",
"caller": "0.0.1",
"minimist": "~0.0.8",
"caller": "~0.0.1",
"core-util-is": "~1.0.1",
"async": "~0.2.10",
"shush": "0.0.1",
"debuglog": "~1.0.1"
"debuglog": "~1.0.1",
"shortstop": "~1.0.0"
}
}

@@ -9,3 +9,3 @@ # confit

[![Build Status](https://travis-ci.org/totherik/confit.png)](https://travis-ci.org/totherik/confit)
[![Build Status](https://travis-ci.org/krakenjs/confit.png)](https://travis-ci.org/krakenjs/confit)

@@ -17,7 +17,6 @@ ## Usage

### confit(options, callback);
* `options` (*String* | *Object*) - the base directory in which config files live
or a configuration object.
* `callback` (*Function*) - the callback to be called with the error or config object.
Signature `function (err, config) { /* ... */}`
### confit([options])
* `options` (*String* | *Object*) - the base directory in which config files live or a configuration object. If no
arguments is provided, defaults to the directory of the calling file. Signature `function (err, config) {}`
* returns - config factory.

@@ -31,3 +30,3 @@ ```javascript

var basedir = path.join(__dirname, 'config');
confit(basedir, function (err, config) {
confit(basedir).create(function (err, config) {
config.get; // Function

@@ -41,2 +40,24 @@ config.set; // Function

### config factory
* `addOverride(filepath)` - Register a file (JSON or JS), the contents of which should be merged with the config datastore.
* `create(callback)` - Creates the config object, ready for use. Callback signature: `function (err, config) {}`
```javascript
// All methods besides `create` are chainable
confit(options)
.addOverride('./mysettings.json')
.addOverride('./mysettings.json')
.create(function (err, config) {
// ...
});
// - or -
//
// var factory = confit(options);
// factory.addOverride('./mysettings.json');
// factory.create(function (err, config) {
// // ...
// });
```
## Options

@@ -66,8 +87,4 @@ * `basedir` (*String*) - the base directory in which config files can be found.

confit(options, function (err, config) {
config.get; // Function
config.set; // Function
config.use; // Function
config.get('env:env'); // 'development'
confit(options).create(function (err, config) {
// ...
});

@@ -77,5 +94,5 @@ ```

## API
* `get(key)` - Retrieve the value for a given key.
* `set(key, value)` - Set a value for the given key.
## Config API
* `get(key)` - Retrieve the value for a given key. Colon-delimited keys can be used to traverse the object hierarchy.
* `set(key, value)` - Set a value for the given key. Colon-delimited keys can be used to traverse the object hierarchy.
* `use(obj)` - merge provided object into config.

@@ -89,2 +106,5 @@

config.get('foo'); // 'baz'
config.use({ a: { b: { c: 'd' } } } );
config.get('a:b:c'); // 'd'
```

@@ -91,0 +111,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc