88 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var tmpl = require('tmpl')
 | |
| 
 | |
| module.exports = makeError
 | |
| 
 | |
| function BaseError() {}
 | |
| BaseError.prototype = new Error()
 | |
| BaseError.prototype.toString = function() {
 | |
|   return this.message
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Makes an Error function with the signature:
 | |
|  *
 | |
|  *   function(message, data)
 | |
|  *
 | |
|  * You'll typically do something like:
 | |
|  *
 | |
|  *   var UnknownFileTypeError = makeError(
 | |
|  *     'UnknownFileTypeError',
 | |
|  *     'The specified type is not known.'
 | |
|  *   )
 | |
|  *   var er = UnknownFileTypeError()
 | |
|  *
 | |
|  * `er` will have a prototype chain that ensures:
 | |
|  *
 | |
|  *   er instanceof Error
 | |
|  *   er instanceof UnknownFileTypeError
 | |
|  *
 | |
|  * You can also do `var er = new UnknownFileTypeError()` if you really like the
 | |
|  * `new` keyword.
 | |
|  *
 | |
|  * @param String  The name of the error.
 | |
|  * @param String  The default message string.
 | |
|  * @param Object  The default data object, merged with per instance data.
 | |
|  */
 | |
| function makeError(name, defaultMessage, defaultData) {
 | |
|   defaultMessage = tmpl(defaultMessage || '')
 | |
|   defaultData = defaultData || {}
 | |
|   if (defaultData.proto && !(defaultData.proto instanceof BaseError))
 | |
|     throw new Error('The custom "proto" must be an Error created via makeError')
 | |
| 
 | |
|   var CustomError = function(message, data) {
 | |
|     if (!(this instanceof CustomError)) return new CustomError(message, data)
 | |
| 
 | |
|     if (typeof message !== 'string' && !data) {
 | |
|       data = message
 | |
|       message = null
 | |
|     }
 | |
| 
 | |
|     this.name = name
 | |
|     this.data = data || defaultData
 | |
| 
 | |
|     if (typeof message === 'string') {
 | |
|       this.message = tmpl(message, this.data)
 | |
|     } else {
 | |
|       this.message = defaultMessage(this.data)
 | |
|     }
 | |
| 
 | |
|     var er = new Error()
 | |
|     this.stack = er.stack
 | |
|     if (this.stack) {
 | |
|       // remove TWO stack level:
 | |
|       if (typeof Components !== 'undefined') {
 | |
|         // Mozilla:
 | |
|         this.stack = this.stack.substring(this.stack.indexOf('\n') + 2)
 | |
|       } else if (typeof chrome !== 'undefined' || typeof process !== 'undefined') {
 | |
|         // Google Chrome/Node.js:
 | |
|         this.stack = this.stack.replace(/\n[^\n]*/, '')
 | |
|         this.stack = this.stack.replace(/\n[^\n]*/, '')
 | |
|         this.stack = (
 | |
|           this.name +
 | |
|           (this.message ? (': ' + this.message) : '') +
 | |
|           this.stack.substring(5)
 | |
|         )
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if ('fileName' in er) this.fileName = er.fileName
 | |
|     if ('lineNumber' in er) this.lineNumber = er.lineNumber
 | |
|   }
 | |
| 
 | |
|   CustomError.prototype = defaultData.proto || new BaseError()
 | |
|   delete defaultData.proto
 | |
| 
 | |
|   return CustomError
 | |
| }
 |