Procházet zdrojové kódy

Initial commit of stand-alone module

James Allen před 8 roky
revize
a94b34f37f

+ 2 - 0
libraries/o-error/.gitignore

@@ -0,0 +1,2 @@
+node_modules/
+

+ 53 - 0
libraries/o-error/index.js

@@ -0,0 +1,53 @@
+'use strict'
+
+var util = require('util')
+
+/**
+ * Make custom error types. There are many, many modules for this, but they all
+ * seem a bit weird. This approach is based on
+ * https://gist.github.com/justmoon/15511f92e5216fa2624b
+ * which seems sensible. This module mainly tries to DRY it up a bit. It also
+ * incorporates some ideas from the verror package. Maybe it can become its own
+ * package one day.
+ *
+ * TODO: Will this work under browserify?
+ *
+ * @module
+ */
+
+function extendErrorType (base, name, builder) {
+  var errorConstructor = function () {
+    Error.captureStackTrace && Error.captureStackTrace(this, this.constructor)
+    if (builder) builder.apply(this, arguments)
+    this.name = name
+  }
+
+  util.inherits(errorConstructor, base)
+
+  errorConstructor.prototype.withCause = function (cause) {
+    this.cause = cause
+    if (this.message && cause.message) {
+      this.message += ': ' + cause.message
+    }
+    return this
+  }
+
+  return errorConstructor
+}
+
+function defineErrorType (name, builder) {
+  return extendErrorType(Error, name, builder)
+}
+
+function extendErrorTypeIn (container, base, name, builder) {
+  container[name] = extendErrorType(base, name, builder)
+}
+
+function defineErrorTypeIn (container, name, builder) {
+  extendErrorTypeIn(container, Error, name, builder)
+}
+
+exports.extend = extendErrorType
+exports.define = defineErrorType
+exports.extendIn = extendErrorTypeIn
+exports.defineIn = defineErrorTypeIn

+ 142 - 0
libraries/o-error/npm-shrinkwrap.json

@@ -0,0 +1,142 @@
+{
+  "name": "overleaf-error-type",
+  "version": "1.0.0",
+  "dependencies": {
+    "chai": {
+      "version": "3.4.1",
+      "from": "chai@>=3.3.0 <4.0.0",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-3.4.1.tgz",
+      "dependencies": {
+        "assertion-error": {
+          "version": "1.0.1",
+          "from": "assertion-error@>=1.0.1 <2.0.0",
+          "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.1.tgz"
+        },
+        "deep-eql": {
+          "version": "0.1.3",
+          "from": "deep-eql@>=0.1.3 <0.2.0",
+          "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+          "dependencies": {
+            "type-detect": {
+              "version": "0.1.1",
+              "from": "type-detect@0.1.1",
+              "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz"
+            }
+          }
+        },
+        "type-detect": {
+          "version": "1.0.0",
+          "from": "type-detect@>=1.0.0 <2.0.0",
+          "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz"
+        }
+      }
+    },
+    "mocha": {
+      "version": "2.3.4",
+      "from": "mocha@>=2.3.3 <3.0.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.3.4.tgz",
+      "dependencies": {
+        "commander": {
+          "version": "2.3.0",
+          "from": "commander@2.3.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz"
+        },
+        "debug": {
+          "version": "2.2.0",
+          "from": "debug@2.2.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+          "dependencies": {
+            "ms": {
+              "version": "0.7.1",
+              "from": "ms@0.7.1",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
+            }
+          }
+        },
+        "diff": {
+          "version": "1.4.0",
+          "from": "diff@1.4.0",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz"
+        },
+        "escape-string-regexp": {
+          "version": "1.0.2",
+          "from": "escape-string-regexp@1.0.2",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz"
+        },
+        "glob": {
+          "version": "3.2.3",
+          "from": "glob@3.2.3",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz",
+          "dependencies": {
+            "graceful-fs": {
+              "version": "2.0.3",
+              "from": "graceful-fs@>=2.0.0 <2.1.0",
+              "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz"
+            },
+            "inherits": {
+              "version": "2.0.1",
+              "from": "inherits@>=2.0.0 <3.0.0",
+              "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+            },
+            "minimatch": {
+              "version": "0.2.14",
+              "from": "minimatch@>=0.2.11 <0.3.0",
+              "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+              "dependencies": {
+                "lru-cache": {
+                  "version": "2.7.3",
+                  "from": "lru-cache@>=2.0.0 <3.0.0",
+                  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz"
+                },
+                "sigmund": {
+                  "version": "1.0.1",
+                  "from": "sigmund@>=1.0.0 <1.1.0",
+                  "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz"
+                }
+              }
+            }
+          }
+        },
+        "growl": {
+          "version": "1.8.1",
+          "from": "growl@1.8.1",
+          "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz"
+        },
+        "jade": {
+          "version": "0.26.3",
+          "from": "jade@0.26.3",
+          "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
+          "dependencies": {
+            "commander": {
+              "version": "0.6.1",
+              "from": "commander@0.6.1",
+              "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz"
+            },
+            "mkdirp": {
+              "version": "0.3.0",
+              "from": "mkdirp@0.3.0",
+              "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz"
+            }
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.0",
+          "from": "mkdirp@0.5.0",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
+          "dependencies": {
+            "minimist": {
+              "version": "0.0.8",
+              "from": "minimist@0.0.8",
+              "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
+            }
+          }
+        },
+        "supports-color": {
+          "version": "1.2.0",
+          "from": "supports-color@1.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz"
+        }
+      }
+    }
+  }
+}

+ 16 - 0
libraries/o-error/package.json

@@ -0,0 +1,16 @@
+{
+  "name": "overleaf-error-type",
+  "version": "1.0.0",
+  "description": "Utility for creating custom error types.",
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha --require test/support"
+  },
+  "author": "team@overleaf.com",
+  "license": "Proprietary",
+  "private": true,
+  "devDependencies": {
+    "chai": "^3.3.0",
+    "mocha": "^2.3.3"
+  }
+}

+ 131 - 0
libraries/o-error/test/error-type.test.js

@@ -0,0 +1,131 @@
+'use strict'
+
+var errorType = require('..')
+
+describe('errorType', function () {
+  it('defines a custom error type', function () {
+    var CustomError = errorType.define('CustomError')
+
+    function doSomethingBad () {
+      throw new CustomError()
+    }
+
+    try {
+      doSomethingBad()
+      expect.fail('should have thrown')
+    } catch (e) {
+      // should set the name to the error's name
+      expect(e.name).to.equal('CustomError')
+
+      // should be an instance of the error type
+      expect(e instanceof CustomError).to.be.true
+
+      // should be an instance of the built-in Error type
+      expect(e instanceof Error).to.be.true
+
+      // should be recognised by util.isError
+      expect(require('util').isError(e)).to.be.true
+
+      // should have a stack trace
+      expect(e.stack).to.be.truthy
+
+      // toString should return the default error message formatting
+      expect(e.toString()).to.equal('CustomError')
+
+      // stack should start with the default error message formatting
+      expect(e.stack.split('\n')[0], 'CustomError')
+
+      // first stack frame should be the function where the error was thrown
+      expect(e.stack.split('\n')[1]).to.match(/doSomethingBad/)
+    }
+  })
+
+  it('defines a custom error type with a message', function () {
+    var CustomError = errorType.define('CustomError', function (x) {
+      this.message = 'x=' + x
+      this.x = x
+    })
+
+    function doSomethingBad () {
+      throw new CustomError('foo')
+    }
+
+    try {
+      doSomethingBad()
+      expect.fail('should have thrown')
+    } catch (e) {
+      expect(e.toString()).to.equal('CustomError: x=foo')
+      expect(e.message).to.equal('x=foo')
+      expect(e.x).to.equal('foo')
+    }
+  })
+
+  it('defines extended error type', function () {
+    var BaseError = errorType.define('BaseError')
+    var DerivedError = errorType.extend(BaseError, 'DerivedError')
+
+    function doSomethingBad () {
+      throw new DerivedError()
+    }
+
+    try {
+      doSomethingBad()
+      expect.fail('should have thrown')
+    } catch (e) {
+      expect(e.toString()).to.equal('DerivedError')
+    }
+  })
+
+  it('defines error types in a container object', function () {
+    var SomeClass = {}
+    errorType.defineIn(SomeClass, 'CustomError')
+
+    function doSomethingBad () {
+      throw new SomeClass.CustomError()
+    }
+
+    try {
+      doSomethingBad()
+      expect.fail('should have thrown')
+    } catch (e) {
+      expect(e.toString()).to.equal('CustomError')
+    }
+  })
+
+  it('extends error types in a container object', function () {
+    var SomeClass = {}
+    errorType.defineIn(SomeClass, 'CustomError', function (payload) {
+      this.message = 'custom error'
+      this.payload = payload
+    })
+    errorType.extendIn(SomeClass, SomeClass.CustomError, 'DerivedCustomError',
+      function (payload) {
+        SomeClass.CustomError.call(this, payload)
+        this.message = 'derived custom error'
+      })
+
+    function doSomethingBad () {
+      throw new SomeClass.CustomError(123)
+    }
+
+    try {
+      doSomethingBad()
+      expect.fail('should have thrown')
+    } catch (e) {
+      expect(e.toString()).to.equal('CustomError: custom error')
+      expect(e.payload).to.equal(123)
+    }
+
+    function doSomethingBadWithDerived () {
+      throw new SomeClass.DerivedCustomError(456)
+    }
+
+    try {
+      doSomethingBadWithDerived()
+      expect.fail('should have thrown')
+    } catch (e) {
+      expect(e.toString()).to.equal('DerivedCustomError: derived custom error')
+      expect(e.payload).to.equal(456)
+    }
+  })
+})

+ 5 - 0
libraries/o-error/test/support/index.js

@@ -0,0 +1,5 @@
+'use strict'
+
+var chai = require('chai')
+
+global.expect = chai.expect