246 lines
6.2 KiB
JavaScript
246 lines
6.2 KiB
JavaScript
![]() |
// Copyright (c) 2012, Mark Cavage. All rights reserved.
|
||
|
|
||
|
var assert = require('assert');
|
||
|
var Stream = require('stream').Stream;
|
||
|
var util = require('util');
|
||
|
|
||
|
|
||
|
|
||
|
///--- Globals
|
||
|
|
||
|
var NDEBUG = process.env.NODE_NDEBUG || false;
|
||
|
var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
|
||
|
|
||
|
|
||
|
|
||
|
///--- Messages
|
||
|
|
||
|
var ARRAY_TYPE_REQUIRED = '%s ([%s]) required';
|
||
|
var TYPE_REQUIRED = '%s (%s) is required';
|
||
|
|
||
|
|
||
|
|
||
|
///--- Internal
|
||
|
|
||
|
function capitalize(str) {
|
||
|
return (str.charAt(0).toUpperCase() + str.slice(1));
|
||
|
}
|
||
|
|
||
|
function uncapitalize(str) {
|
||
|
return (str.charAt(0).toLowerCase() + str.slice(1));
|
||
|
}
|
||
|
|
||
|
function _() {
|
||
|
return (util.format.apply(util, arguments));
|
||
|
}
|
||
|
|
||
|
|
||
|
function _assert(arg, type, name, stackFunc) {
|
||
|
if (!NDEBUG) {
|
||
|
name = name || type;
|
||
|
stackFunc = stackFunc || _assert.caller;
|
||
|
var t = typeof (arg);
|
||
|
|
||
|
if (t !== type) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(TYPE_REQUIRED, name, type),
|
||
|
actual: t,
|
||
|
expected: type,
|
||
|
operator: '===',
|
||
|
stackStartFunction: stackFunc
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function _instanceof(arg, type, name, stackFunc) {
|
||
|
if (!NDEBUG) {
|
||
|
name = name || type;
|
||
|
stackFunc = stackFunc || _instanceof.caller;
|
||
|
|
||
|
if (!(arg instanceof type)) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(TYPE_REQUIRED, name, type.name),
|
||
|
actual: _getClass(arg),
|
||
|
expected: type.name,
|
||
|
operator: 'instanceof',
|
||
|
stackStartFunction: stackFunc
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function _getClass(object) {
|
||
|
return (Object.prototype.toString.call(object).slice(8, -1));
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
///--- API
|
||
|
|
||
|
function array(arr, type, name) {
|
||
|
if (!NDEBUG) {
|
||
|
name = name || type;
|
||
|
|
||
|
if (!Array.isArray(arr)) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(ARRAY_TYPE_REQUIRED, name, type),
|
||
|
actual: typeof (arr),
|
||
|
expected: 'array',
|
||
|
operator: 'Array.isArray',
|
||
|
stackStartFunction: array.caller
|
||
|
});
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < arr.length; i++) {
|
||
|
_assert(arr[i], type, name, array);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function bool(arg, name) {
|
||
|
_assert(arg, 'boolean', name, bool);
|
||
|
}
|
||
|
|
||
|
|
||
|
function buffer(arg, name) {
|
||
|
if (!Buffer.isBuffer(arg)) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(TYPE_REQUIRED, name || '', 'Buffer'),
|
||
|
actual: typeof (arg),
|
||
|
expected: 'buffer',
|
||
|
operator: 'Buffer.isBuffer',
|
||
|
stackStartFunction: buffer
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function func(arg, name) {
|
||
|
_assert(arg, 'function', name);
|
||
|
}
|
||
|
|
||
|
|
||
|
function number(arg, name) {
|
||
|
_assert(arg, 'number', name);
|
||
|
if (!NDEBUG && (isNaN(arg) || !isFinite(arg))) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(TYPE_REQUIRED, name, 'number'),
|
||
|
actual: arg,
|
||
|
expected: 'number',
|
||
|
operator: 'isNaN',
|
||
|
stackStartFunction: number
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function object(arg, name) {
|
||
|
_assert(arg, 'object', name);
|
||
|
}
|
||
|
|
||
|
|
||
|
function stream(arg, name) {
|
||
|
_instanceof(arg, Stream, name);
|
||
|
}
|
||
|
|
||
|
|
||
|
function date(arg, name) {
|
||
|
_instanceof(arg, Date, name);
|
||
|
}
|
||
|
|
||
|
function regexp(arg, name) {
|
||
|
_instanceof(arg, RegExp, name);
|
||
|
}
|
||
|
|
||
|
|
||
|
function string(arg, name) {
|
||
|
_assert(arg, 'string', name);
|
||
|
}
|
||
|
|
||
|
|
||
|
function uuid(arg, name) {
|
||
|
string(arg, name);
|
||
|
if (!NDEBUG && !UUID_REGEXP.test(arg)) {
|
||
|
throw new assert.AssertionError({
|
||
|
message: _(TYPE_REQUIRED, name, 'uuid'),
|
||
|
actual: 'string',
|
||
|
expected: 'uuid',
|
||
|
operator: 'test',
|
||
|
stackStartFunction: uuid
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///--- Exports
|
||
|
|
||
|
module.exports = {
|
||
|
bool: bool,
|
||
|
buffer: buffer,
|
||
|
date: date,
|
||
|
func: func,
|
||
|
number: number,
|
||
|
object: object,
|
||
|
regexp: regexp,
|
||
|
stream: stream,
|
||
|
string: string,
|
||
|
uuid: uuid
|
||
|
};
|
||
|
|
||
|
|
||
|
Object.keys(module.exports).forEach(function (k) {
|
||
|
if (k === 'buffer')
|
||
|
return;
|
||
|
|
||
|
var name = 'arrayOf' + capitalize(k);
|
||
|
|
||
|
if (k === 'bool')
|
||
|
k = 'boolean';
|
||
|
if (k === 'func')
|
||
|
k = 'function';
|
||
|
module.exports[name] = function (arg, name) {
|
||
|
array(arg, k, name);
|
||
|
};
|
||
|
});
|
||
|
|
||
|
Object.keys(module.exports).forEach(function (k) {
|
||
|
var _name = 'optional' + capitalize(k);
|
||
|
var s = uncapitalize(k.replace('arrayOf', ''));
|
||
|
if (s === 'bool')
|
||
|
s = 'boolean';
|
||
|
if (s === 'func')
|
||
|
s = 'function';
|
||
|
|
||
|
if (k.indexOf('arrayOf') !== -1) {
|
||
|
module.exports[_name] = function (arg, name) {
|
||
|
if (!NDEBUG && arg !== undefined) {
|
||
|
array(arg, s, name);
|
||
|
}
|
||
|
};
|
||
|
} else {
|
||
|
module.exports[_name] = function (arg, name) {
|
||
|
if (!NDEBUG && arg !== undefined) {
|
||
|
_assert(arg, s, name);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
// Reexport built-in assertions
|
||
|
Object.keys(assert).forEach(function (k) {
|
||
|
if (k === 'AssertionError') {
|
||
|
module.exports[k] = assert[k];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
module.exports[k] = function () {
|
||
|
if (!NDEBUG) {
|
||
|
assert[k].apply(assert[k], arguments);
|
||
|
}
|
||
|
};
|
||
|
});
|