// 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); } }; });