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.
		
		
		
		
		
			
		
			
				
					212 lines
				
				5.3 KiB
			
		
		
			
		
	
	
					212 lines
				
				5.3 KiB
			| 
											3 years ago
										 | // 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); |