<|start_filename|>index.js<|end_filename|>
var errors = [];

function addError(name, code) {
    var codes = [].slice.call(arguments, 1);
    var re = new RegExp("^(" + codes.join("|") + ")$");
    errors.push({
        name: name,
        class: createClass(name, code, function(e) {
            if (!e) return false;
            if ("cause" in e && typeof e.cause.code === "string") {
                return re.test(e.cause.code);
            } else if (typeof e.code === "string") {
                return re.test(e.code);
            } else {
                return false;
            }
        })
    });
}

function createClass(name, defaultCode, predicate) {
    var CustomError = (new Function('name', 'defaultCode', 'predicate', [
            '"use strict";',
            'return function ' + name + '(message, code) {',
            '  if (this === undefined) return message instanceof ' + name + ' ? true : predicate(message);',
            '  Error.captureStackTrace(this, "' + name + '");',
            '  Error.call(this);',
            '  this.name = name;',
            '  this.message = message;',
            '  this.code = code === undefined ? defaultCode : code;',
            '}'
        ].join('\n')))(name, defaultCode, predicate);

    CustomError.prototype = Object.create(Error.prototype, {
        constructor: {
            value: CustomError,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
    if (typeof Object.setPrototypeOf === 'function') {
        Object.setPrototypeOf(CustomError, Error);
    }
    else {
        CustomError.__proto__ = Error;
    }

    return CustomError;
}

addError("FileNotFoundError", "ENOENT");
addError("FileAccessError", "EACCES", "EPERM");
addError("EOFError", "EOF");
addError("UnknownHostError", "EADDRINFO");
addError("SocketError", "EISCONN", "ENOTCONN", "ENOTSOCK",
                        "ENOTSUP", "EPROTOTYPE", "EAIFAMNOSUPPORT",
                        "EAISERVICE");
addError("ProtocolError", "EPROTO", "EPROTONOSUPPORT", "EPROTOTYPE");
addError("FileSystemError", "EBUSY", "ENOENT", "EOF", "EACCES", "EAGAIN",
                            "EBADF", "EMFILE", "ENOTDIR", "EISDIR", "EEXIST",
                            "ENAMETOOLONG", "EPERM", "ELOOP", "ENOTEMPTY",
                            "ENOSPC", "EIO", "EROFS", "ENODEV", "ESPIPE",
                            "ECANCELED", "ENFILE", "EXDEV");
addError("ConnectError", "ECONNABORTED", "ECONNREFUSED", "ECONNRESET", "ETIMEDOUT");
addError("BindError", "EADDRNOTAVAIL");
addError("AddressNotFoundError", "ENOTFOUND");
addError("NetworkError", "EADDRINFO", "EADDRNOTAVAIL", "EAFNOSUPPORT",
                        "EALREADY", "ECONNABORTED", "ECONNREFUSED",
                        "ECONNRESET", "EDESTADDRREQ", "EHOSTUNREACH",
                        "EISCONN", "EMSGSIZE", "ENETDOWN", "ENETUNREACH",
                        "ENONET", "ENOTCONN", "ENOTSOCK", "ENOTSUP", "EPIPE",
                        "EPROTO",  "EPROTONOSUPPORT", "EPROTOTYPE",
                        "ETIMEDOUT", "EAIFAMNOSUPPORT", "EAISERVICE",
                        "EAISOCKTYPE", "ESHUTDOWN", "ENOTFOUND");

errors.push({
    name: "SSLError",
    class: createClass("SSLError", ["SSLERROR"], function(e) {
        var re = /^SSL Error:/;
        if (!e) return false;
        if ("cause" in e && typeof e.cause.message === "string") {
            return re.test(e.cause.message);
        } else if (typeof e.message === "string") {
            return re.test(e.message);
        } else {
            return false;
        }
    })
});


errors.forEach(function(error) {
    module.exports[error.name] = error.class;
});

module.exports.globalize = function() {
    errors.forEach(function(error) {
        if (global[error.name] === undefined) {
            global[error.name] = error.class;
        }
    });
    return this;
};




<|start_filename|>test/test.js<|end_filename|>
require("../index.js").globalize();
var assert = require("assert");

function errorWithCode(code) {
    var ret = new Error();
    ret.code = code;
    return ret;
}

function errorWithCause(code) {
    var ret = new Error();
    ret.cause = new Error();
    ret.cause.code = code;
    return ret;
}


function testType(type, codes) {
    codes = [].slice.call(arguments, 1);
    var predicate = global[type];
    describe(type, function() {
        codes.forEach(function(code) {
            describe("returns true when the direct error has code", function() {
                specify(code, function() {
                    assert.strictEqual(predicate(errorWithCode(code)), true);
                });
            });
            describe("returns true when the error cause has code", function() {
                specify(code, function() {
                    assert.strictEqual(predicate(errorWithCause(code)), true);
                });
            });

            describe("creates new instance, without arguments", function () {
                specify(code, function () {
                    var instance = new predicate();
                    assert.strictEqual(instance instanceof Error, true);
                    assert.strictEqual(instance instanceof predicate, true);
                    assert.strictEqual(instance.code, codes[0]);
                });
            });

            describe("creates a new instance, with message argument", function () {
                specify(code, function () {
                    var instance = new predicate("Something went wrong");
                    assert.strictEqual(instance.code, codes[0]);
                    assert.strictEqual(instance.message, "Something went wrong");
                });
            });

            describe("creates a new instance, with message and code arguments", function () {
                specify(code, function () {
                    var instance = new predicate("Something went wrong", code);
                    assert.strictEqual(instance.code, code);
                    assert.strictEqual(instance.message, "Something went wrong");
                });
            });

            describe("predicate matches instance with default code", function () {
                specify(code, function () {
                    var instance = new predicate();
                    assert.strictEqual(predicate(instance), true);
                });
            });

            describe("predicate matches instance with specific code", function () {
                specify(code, function () {
                    var instance = new predicate("Error", code);
                    assert.strictEqual(predicate(instance), true);
                });
            });

        });

        it("doesn't cause errors with weird objects", function() {
            assert.strictEqual(predicate(false), false);
            assert.strictEqual(predicate(Object.create(null)), false);
        });

        it("matches instance with specific code, even if the code is not recognized", function () {
            var instance = new predicate("Error", "nonsense");
            assert.strictEqual(predicate(instance), true);
        });

        it('is throwable', function () {
            try {
                throw new predicate("Error");
            }
            catch (e) {
                assert.strictEqual(predicate(e), true);
            }
        });
    });
}

testType("FileNotFoundError", "ENOENT");
testType("FileAccessError", "EACCES", "EPERM");
testType("EOFError", "EOF");
testType("UnknownHostError", "EADDRINFO");
testType("SocketError", "EISCONN", "ENOTCONN", "ENOTSOCK",
                        "ENOTSUP", "EPROTOTYPE", "EAIFAMNOSUPPORT",
                        "EAISERVICE");
testType("ProtocolError", "EPROTO", "EPROTONOSUPPORT", "EPROTOTYPE");
testType("FileSystemError", "EBUSY", "ENOENT", "EOF", "EACCES", "EAGAIN",
                            "EBADF", "EMFILE", "ENOTDIR", "EISDIR", "EEXIST",
                            "ENAMETOOLONG", "EPERM", "ELOOP", "ENOTEMPTY",
                            "ENOSPC", "EIO", "EROFS", "ENODEV", "ESPIPE",
                            "ECANCELED", "ENFILE", "EXDEV");
testType("ConnectError", "ECONNABORTED", "ECONNREFUSED", "ECONNRESET", "ETIMEDOUT");
testType("BindError", "EADDRNOTAVAIL");
testType("AddressNotFoundError", "ENOTFOUND");
testType("NetworkError", "EADDRINFO", "EADDRNOTAVAIL", "EAFNOSUPPORT",
                        "EALREADY", "ECONNABORTED", "ECONNREFUSED",
                        "ECONNRESET", "EDESTADDRREQ", "EHOSTUNREACH",
                        "EISCONN", "EMSGSIZE", "ENETDOWN", "ENETUNREACH",
                        "ENONET", "ENOTCONN", "ENOTSOCK", "ENOTSUP", "EPIPE",
                        "EPROTO",  "EPROTONOSUPPORT", "EPROTOTYPE",
                        "ETIMEDOUT", "EAIFAMNOSUPPORT", "EAISERVICE",
                        "EAISOCKTYPE", "ESHUTDOWN", "ENOTFOUND");

describe("SSLError", function() {
    specify("returns true when the direct error begins with the SSL error message", function() {
        var error = new Error("SSL Error:");
        assert.strictEqual(SSLError(error), true);
    });
    specify("returns true when the error cause begins with the SSL error message", function() {
        var error = new Error();
        error.cause = new Error("SSL Error:");
        assert.strictEqual(SSLError(error), true);
    });

    specify("doesn't cause errors with weird objects", function() {
        assert.strictEqual(SSLError(false), false);
        assert.strictEqual(SSLError(Object.create(null)), false);
    });

    it("matches instance with specific code, even if the code is not recognized", function () {
        var instance = new SSLError("Error", "nonsense");
        assert.strictEqual(SSLError(instance), true);
    });

    it('is throwable', function () {
        try {
            throw new SSLError("Error");
        }
        catch (e) {
            assert.strictEqual(SSLError(e), true);
        }
    });
});


<|start_filename|>package.json<|end_filename|>
{
  "name": "core-error-predicates",
  "version": "1.1.0",
  "description": "Error predicate functions for operational errors thrown by node core",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/petkaantonov/core-error-predicates.git"
  },
  "keywords": [
    "error",
    "errors",
    "patternmatching",
    "dsl"
  ],
  "author": "<NAME> <<EMAIL>> (https://github.com/petkaantonov/)",
  "license": "MIT",
  "devDependencies": {
    "mocha": "^2.1.0"
  },
  "readmeFilename": "README.md",
  "files": [
    "LICENSE",
    "index.js"
  ]
}
