Allow asteroid modules to define and validate options

This commit is contained in:
Ritchie Martori 2013-04-15 12:36:37 -07:00
parent fc8afa066e
commit 621b845978
13 changed files with 227 additions and 16 deletions

View File

@ -0,0 +1,7 @@
{
"module": "oracle-connection",
"options": {
"hostname": "127.0.0.1",
"port": 1234
}
}

View File

@ -25,4 +25,36 @@ A configuration then must define:
}
}
Where `some-model-module` is an existing `model` instance.
Where `some-model-module` is an existing `model` instance.
## AsteroidModule.options
Asteroid Modules may also describe the options they accept. This will validate the configuration and make sure users have supplied required information and in a way that the module can use to construct a working instance.
Here is an example options description for the [oracle database connection module](../connections/oracle-connection).
// must come after `inherits()`
OracleConnection.defineOption('hostname', 'string', {required: true});
OracleConnection.defineOption('port', 'number', {min: 10, max: 99999});
OracleConnection.defineOption('username', 'string');
OracleConnection.defineOption('password', 'string');
### AsteroidModule.defineOption(key, type, [options])
**key** the option name given in `config.json`.
**type** must be one of:
- string
- boolean
- number
- array
**options** depend on the type
{
required: true, // options are optional by default
min: 10, // minimum length or value
max: 100, // max length or value
}

View File

@ -1,12 +0,0 @@
/**
* A generated `AsteroidModule` example...
*
* Examples should show a working module api
* and be used in tests to continously check
* they function as expected.
*/
var AsteroidModule = require('../');
var asteroidModule = AsteroidModule.create();
asteroidModule.myMethod();

View File

@ -27,7 +27,7 @@ function AsteroidModule(options) {
// throw an error if args are not supplied
assert(typeof options === 'object', 'AsteroidModule requires an options object');
this.options = options;
this.options = validateOptions(options, this.constructor.optionsDefinition);
debug('created with options', options);
}
@ -36,4 +36,54 @@ function AsteroidModule(options) {
* Inherit from `Module`.
*/
inherits(AsteroidModule, Module);
inherits(AsteroidModule, Module);
/**
* Define an option of the given key/name with the provided type.
*/
AsteroidModule.defineOption = function (key, type, options) {
var od = this.optionsDefinition = this.optionsDefinition || {};
options = options || {};
options.type = type;
od[key] = options;
}
function validateOptions(options, def) {
if(!def) {
return options;
}
Object.keys(def).forEach(function (key) {
var val = options[key];
var keyDef = def[key] || {};
if(keyDef.required) {
assert(val, key + ' is required!');
}
// type
assert(typeof val == keyDef.type, key + ' must be a ' + keyDef.type);
// size / length
if(typeof val.length === 'number') {
if(keyDef.min) {
assert(val.length >= keyDef.min, key + ' length must be greater than or equal to ', keyDef.min);
}
if(keyDef.max) {
assert(val.length <= keyDef.min, key + ' length must be less than or equal to ', keyDef.max);
}
} else if(typeof val === 'number') {
if(keyDef.min) {
assert(val >= keyDef.min, key + ' must be greater than or equal to ', keyDef.min);
}
if(keyDef.max) {
assert(val <= keyDef.max, ' must be less than or equal to ', keyDef.max);
}
}
});
return options;
}

View File

@ -9,7 +9,6 @@ module.exports = Connection;
*/
var AsteroidModule = require('asteroid-module')
,
, debug = require('debug')('connection')
, util = require('util')
, inherits = util.inherits
@ -26,6 +25,13 @@ function Connection(options) {
AsteroidModule.apply(this, arguments);
this.options = options;
// inheriting connections must provide an adapter
// otherwise throw when this connection's adapter
// is used...
this.adapter = function () {
throw new Error('connection has not provided an adapter!');
}
debug('created with options', options);
}

10
node_modules/connections/oracle-connection/.gitignore generated vendored Normal file
View File

@ -0,0 +1,10 @@
.DS_Store
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.swp
*.swo
node_modules/

13
node_modules/connections/oracle-connection/README.md generated vendored Normal file
View File

@ -0,0 +1,13 @@
# connection
## About
Provides a base class for implementing access to a persistence layer.
### Options
#### hostname
#### port
#### database
#### username
#### password

View File

@ -0,0 +1,12 @@
/**
* A generated `Connection` example...
*
* Examples should show a working module api
* and be used in tests to continously check
* they function as expected.
*/
var Connection = require('../');
var connection = Connection.create();
connection.myMethod();

5
node_modules/connections/oracle-connection/index.js generated vendored Normal file
View File

@ -0,0 +1,5 @@
/**
* connection ~ public api
*/
module.exports = require('./lib/connection');

View File

@ -0,0 +1,44 @@
/**
* Expose `OracleConnection`.
*/
module.exports = OracleConnection;
/**
* Module dependencies.
*/
var Connection = require('asteroid-module')
, debug = require('debug')('connection')
, util = require('util')
, inherits = util.inherits
, assert = require('assert');
/**
* Create a new `OracleConnection` with the given `options`.
*
* @param {Object} options
* @return {Connection}
*/
function OracleConnection(options) {
AsteroidModule.apply(this, arguments);
this.options = options;
debug('created with options', options);
}
/**
* Inherit from `AsteroidModule`.
*/
inherits(OracleConnection, Connection);
/**
* Define options.
*/
OracleConnection.defineOption('hostname', 'string', {required: true});
OracleConnection.defineOption('port', 'number', {min: 10, max: 99999});
OracleConnection.defineOption('username', 'string');
OracleConnection.defineOption('password', 'string');

View File

@ -0,0 +1,15 @@
{
"name": "oracle-connection",
"description": "connection",
"version": "0.0.1",
"scripts": {
"test": "mocha"
},
"dependencies": {
"jugglingdb-oracle": "latest",
"debug": "latest"
},
"devDependencies": {
"mocha": "latest"
}
}

View File

@ -0,0 +1,24 @@
var Connection = require('../');
describe('Connection', function(){
var connection;
beforeEach(function(){
connection = new Connection;
});
describe('.myMethod', function(){
// example sync test
it('should <description of behavior>', function() {
connection.myMethod();
});
// example async test
it('should <description of behavior>', function(done) {
setTimeout(function () {
connection.myMethod();
done();
}, 0);
});
});
});

View File

@ -0,0 +1,5 @@
/**
* connection test setup and support.
*/
assert = require('assert');