You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.3 KiB
211 lines
5.3 KiB
// Copyright (c) 2012, Mark Cavage. All rights reserved. |
|
// Copyright 2015 Joyent, Inc. |
|
|
|
var assert = require('assert'); |
|
var Stream = require('stream').Stream; |
|
var util = require('util'); |
|
|
|
|
|
///--- Globals |
|
|
|
/* JSSTYLED */ |
|
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}$/; |
|
|
|
|
|
///--- Internal |
|
|
|
function _capitalize(str) { |
|
return (str.charAt(0).toUpperCase() + str.slice(1)); |
|
} |
|
|
|
function _toss(name, expected, oper, arg, actual) { |
|
throw new assert.AssertionError({ |
|
message: util.format('%s (%s) is required', name, expected), |
|
actual: (actual === undefined) ? typeof (arg) : actual(arg), |
|
expected: expected, |
|
operator: oper || '===', |
|
stackStartFunction: _toss.caller |
|
}); |
|
} |
|
|
|
function _getClass(arg) { |
|
return (Object.prototype.toString.call(arg).slice(8, -1)); |
|
} |
|
|
|
function noop() { |
|
// Why even bother with asserts? |
|
} |
|
|
|
|
|
///--- Exports |
|
|
|
var types = { |
|
bool: { |
|
check: function (arg) { return typeof (arg) === 'boolean'; } |
|
}, |
|
func: { |
|
check: function (arg) { return typeof (arg) === 'function'; } |
|
}, |
|
string: { |
|
check: function (arg) { return typeof (arg) === 'string'; } |
|
}, |
|
object: { |
|
check: function (arg) { |
|
return typeof (arg) === 'object' && arg !== null; |
|
} |
|
}, |
|
number: { |
|
check: function (arg) { |
|
return typeof (arg) === 'number' && !isNaN(arg); |
|
} |
|
}, |
|
finite: { |
|
check: function (arg) { |
|
return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg); |
|
} |
|
}, |
|
buffer: { |
|
check: function (arg) { return Buffer.isBuffer(arg); }, |
|
operator: 'Buffer.isBuffer' |
|
}, |
|
array: { |
|
check: function (arg) { return Array.isArray(arg); }, |
|
operator: 'Array.isArray' |
|
}, |
|
stream: { |
|
check: function (arg) { return arg instanceof Stream; }, |
|
operator: 'instanceof', |
|
actual: _getClass |
|
}, |
|
date: { |
|
check: function (arg) { return arg instanceof Date; }, |
|
operator: 'instanceof', |
|
actual: _getClass |
|
}, |
|
regexp: { |
|
check: function (arg) { return arg instanceof RegExp; }, |
|
operator: 'instanceof', |
|
actual: _getClass |
|
}, |
|
uuid: { |
|
check: function (arg) { |
|
return typeof (arg) === 'string' && UUID_REGEXP.test(arg); |
|
}, |
|
operator: 'isUUID' |
|
} |
|
}; |
|
|
|
function _setExports(ndebug) { |
|
var keys = Object.keys(types); |
|
var out; |
|
|
|
/* re-export standard assert */ |
|
if (process.env.NODE_NDEBUG) { |
|
out = noop; |
|
} else { |
|
out = function (arg, msg) { |
|
if (!arg) { |
|
_toss(msg, 'true', arg); |
|
} |
|
}; |
|
} |
|
|
|
/* standard checks */ |
|
keys.forEach(function (k) { |
|
if (ndebug) { |
|
out[k] = noop; |
|
return; |
|
} |
|
var type = types[k]; |
|
out[k] = function (arg, msg) { |
|
if (!type.check(arg)) { |
|
_toss(msg, k, type.operator, arg, type.actual); |
|
} |
|
}; |
|
}); |
|
|
|
/* optional checks */ |
|
keys.forEach(function (k) { |
|
var name = 'optional' + _capitalize(k); |
|
if (ndebug) { |
|
out[name] = noop; |
|
return; |
|
} |
|
var type = types[k]; |
|
out[name] = function (arg, msg) { |
|
if (arg === undefined || arg === null) { |
|
return; |
|
} |
|
if (!type.check(arg)) { |
|
_toss(msg, k, type.operator, arg, type.actual); |
|
} |
|
}; |
|
}); |
|
|
|
/* arrayOf checks */ |
|
keys.forEach(function (k) { |
|
var name = 'arrayOf' + _capitalize(k); |
|
if (ndebug) { |
|
out[name] = noop; |
|
return; |
|
} |
|
var type = types[k]; |
|
var expected = '[' + k + ']'; |
|
out[name] = function (arg, msg) { |
|
if (!Array.isArray(arg)) { |
|
_toss(msg, expected, type.operator, arg, type.actual); |
|
} |
|
var i; |
|
for (i = 0; i < arg.length; i++) { |
|
if (!type.check(arg[i])) { |
|
_toss(msg, expected, type.operator, arg, type.actual); |
|
} |
|
} |
|
}; |
|
}); |
|
|
|
/* optionalArrayOf checks */ |
|
keys.forEach(function (k) { |
|
var name = 'optionalArrayOf' + _capitalize(k); |
|
if (ndebug) { |
|
out[name] = noop; |
|
return; |
|
} |
|
var type = types[k]; |
|
var expected = '[' + k + ']'; |
|
out[name] = function (arg, msg) { |
|
if (arg === undefined || arg === null) { |
|
return; |
|
} |
|
if (!Array.isArray(arg)) { |
|
_toss(msg, expected, type.operator, arg, type.actual); |
|
} |
|
var i; |
|
for (i = 0; i < arg.length; i++) { |
|
if (!type.check(arg[i])) { |
|
_toss(msg, expected, type.operator, arg, type.actual); |
|
} |
|
} |
|
}; |
|
}); |
|
|
|
/* re-export built-in assertions */ |
|
Object.keys(assert).forEach(function (k) { |
|
if (k === 'AssertionError') { |
|
out[k] = assert[k]; |
|
return; |
|
} |
|
if (ndebug) { |
|
out[k] = noop; |
|
return; |
|
} |
|
out[k] = assert[k]; |
|
}); |
|
|
|
/* export ourselves (for unit tests _only_) */ |
|
out._setExports = _setExports; |
|
|
|
return out; |
|
} |
|
|
|
module.exports = _setExports(process.env.NODE_NDEBUG);
|
|
|