Skip to content

Commit dc9cd0d

Browse files
author
aeb
committed
Nodeerrors can be used inside modules. Major version bump
1 parent 985c718 commit dc9cd0d

File tree

17 files changed

+231
-214
lines changed

17 files changed

+231
-214
lines changed

lib/nodeerrors.js

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,71 @@
11
"use strict";
2-
var _ = require("underscore");
3-
var errorCodeSpecs = require("./util/getErrorConfig");
2+
delete require.cache[__filename]; //do not cache in require cache
3+
var getErrorConfig = require("./util/getErrorConfig");
44
var makeErrorFunction = require("./util/makeErrorFunction");
5+
var getErrorConfigFilePath = require("./util/getErrorConfigFilePath");
56
var parse = require("./util/parse");
67
var middleware = require("./middleware");
8+
var cache = require("./util/cache"); //use requires caching to have a singleton
9+
var path = require("path");
710

8-
var nodeError = {
9-
errorCodes:{},
10-
parse:parse,
11-
middleware:middleware
12-
};
13-
14-
var functionsToMake = _.keys(errorCodeSpecs); //get array of friendly names.
15-
for (var i = 0; i < functionsToMake.length; i++) {
16-
//get error code friendly name, for example: "internalError"
17-
var errorCodeName = functionsToMake[i];
18-
//make error function for friendly name
19-
nodeError[errorCodeName] = makeErrorFunction(errorCodeName, errorCodeSpecs[errorCodeName]);
20-
//save the error code in errorCodes
21-
nodeError.errorCodes[errorCodeName] = errorCodeName;
22-
}
11+
function getNodeErrors() {
12+
var startDir = path.dirname(module.parent.filename);
13+
var errorConfigFilePath;
14+
if (cache.errorConfigFilePaths[startDir]) {
15+
errorConfigFilePath = cache.errorConfigFilePaths[startDir];
16+
} else {
17+
errorConfigFilePath = getErrorConfigFilePath(startDir);
18+
if(!errorConfigFilePath){
19+
throw new Error("nodeerrors, cannot find .errors.js, starting from path " + startDir);
20+
}
21+
cache.errorConfigFilePaths[startDir] = errorConfigFilePath;
22+
}
23+
if (cache.nodeerrors[errorConfigFilePath]) {
24+
return cache.nodeerrors[errorConfigFilePath];
25+
}
2326

24-
Error.prototype.innerError = function addInnerError(err) {
25-
this.internal = this.internal || {};
26-
this.internal.innerError = err;
27-
return this;
28-
};
27+
if (!cache.prototypesExtended) {
28+
cache.prototypesExtended = true;
29+
Error.prototype.innerError = function addInnerError(err) {
30+
this.internal = this.internal || {};
31+
this.internal.innerError = err;
32+
return this;
33+
};
34+
Function.prototype.onError = function (callback) {
35+
var fn = this;
36+
return function (err) {
37+
if (err) {
38+
return callback(err);
39+
}
40+
try {
41+
fn.apply(null, arguments);
42+
} catch (ex) {
43+
return callback(ex);
44+
}
45+
};
46+
};
47+
}
2948

30-
Function.prototype.onError = function (callback) {
31-
var fn = this;
32-
return function (err) {
33-
if (err) {
34-
return callback(err);
35-
}
36-
try {
37-
fn.apply(null, arguments);
38-
} catch (ex) {
39-
return callback(ex);
40-
}
49+
//Not in cache, create nodeErrors object
50+
var nodeError = {
51+
errorCodes:{},
52+
middleware:middleware
4153
};
42-
};
54+
nodeError.parse = parse.bind(nodeError);
55+
var errorCodeSpecs = getErrorConfig(errorConfigFilePath);
56+
57+
var functionsToMake = Object.keys(errorCodeSpecs); //get array of friendly names.
58+
for (var i = 0; i < functionsToMake.length; i++) {
59+
//get error code friendly name, for example: "internalError"
60+
var errorCodeName = functionsToMake[i];
61+
//make error function for friendly name
62+
nodeError[errorCodeName] = makeErrorFunction(errorCodeName, errorCodeSpecs[errorCodeName]);
63+
//save the error code in errorCodes
64+
nodeError.errorCodes[errorCodeName] = errorCodeName;
65+
}
66+
67+
cache.nodeerrors[errorConfigFilePath] = nodeError;
68+
return nodeError;
69+
}
4370

44-
module.exports = nodeError;
71+
module.exports = getNodeErrors();

lib/util/cache.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
errorConfigFilePaths : {}, //lookup error configs based on dir name from witch require was called, here
3+
nodeerrors :{} //lookup nodeErrors object based on errorConfigFilePath here
4+
}; //cache singleton

lib/util/getErrorConfig.js

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,15 @@
11
"use strict";
2-
var _ = require("underscore");
3-
var path = require("path");
4-
var fs = require("fs");
5-
var existsSync = fs.existsSync || path.existsSync;
6-
var CONFIG_FILE_NAME = ".errors.js";
72

8-
function requireConfig() {
9-
var dir = path.join(__dirname, "../..");
10-
var lastDir;
11-
12-
while (lastDir !== dir) {
13-
if (existsSync(path.join(dir, CONFIG_FILE_NAME))) {
14-
return require(path.join(dir, CONFIG_FILE_NAME));
15-
}
16-
if (existsSync(path.join(dir, "config", CONFIG_FILE_NAME))) {
17-
return require(path.join(dir, "config", CONFIG_FILE_NAME));
18-
}
19-
lastDir = dir;
20-
dir = path.join(dir, "..");
3+
function getErrorConfig(filePath) {
4+
var config = JSON.parse(JSON.stringify(require(filePath))); //make copy so we do not alter original
5+
if (!config.system) {
6+
config.system = {
7+
message:"There was an internal server error",
8+
http:500
9+
};
2110
}
22-
return {};
23-
}
24-
var config = JSON.parse(JSON.stringify(requireConfig())); //make copy so we do not alter original
25-
if (!config.system) {
26-
config.system = {
27-
message:"There was an internal server error",
28-
http:500
29-
};
11+
return config;
3012
}
3113

32-
module.exports = config;
14+
module.exports = getErrorConfig;
3315

lib/util/getErrorConfigFilePath.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use strict";
2+
var path = require("path");
3+
var fs = require("fs");
4+
var existsSync = fs.existsSync || path.existsSync;
5+
var FILE_NAME = ".errors.js";
6+
7+
module.exports = function getErrorConfigFilePath(startDir) {
8+
var dir = startDir;
9+
var lastDir;
10+
while (lastDir !== dir) {
11+
if (existsSync(path.join(dir, FILE_NAME))) {
12+
return path.join(dir, FILE_NAME);
13+
}
14+
if (existsSync(path.join(dir, "config", FILE_NAME))) {
15+
return path.join(dir, "config", FILE_NAME);
16+
}
17+
lastDir = dir;
18+
dir = path.join(dir, "..");
19+
}
20+
return false;
21+
};

lib/util/parse.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ var uuid = require("node-uuid");
33
var getSerializableError = require("./getSerializableError");
44

55
module.exports = function parseError(err) {
6-
var errors = require("../nodeerrors.js");
6+
var errors = this;
77
var error;
88
if(err && err.internal && err.internal.nodeErrors){
99
error = getSerializableError(err);
1010
} else {
1111
//this is not one of our errors, must be from mongo or somewhere else, no recovery possible.
12-
error = parseError(errors.system().innerError(err));
12+
error = parseError.call(this, errors.system().innerError(err));
1313
}
1414
if(!error.id){
1515
error.id = uuid.v4();

package.json

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,45 @@
11
{
2-
"author":"Allan Ebdrup",
3-
"name":"nodeerrors",
4-
"description":"error handling module for node",
5-
"version":"1.2.0",
6-
"repository":{
7-
"type":"git",
8-
"url":"https://github.com/Muscula/nodeerrors"
9-
},
10-
"private":false,
11-
"main":"./lib/nodeerrors.js",
12-
"engines":{
13-
"node":">=0.6.20",
14-
"npm":">=1.1.9"
15-
},
16-
"dependencies":{
17-
"underscore":"~1.3.1",
18-
"node-uuid":"~1.4.0"
19-
},
20-
"scripts":{
21-
"test":"node ./bin/runTests.js"
22-
},
23-
"devDependencies":{
24-
"mocha":"",
25-
"chai":"",
26-
"sinon":"",
27-
"sinon-chai":"",
28-
"jshint":"",
29-
"requiremock":">=1.3.3",
30-
"request":""
31-
}
2+
"author": "Allan Ebdrup",
3+
"name": "nodeerrors",
4+
"description": "error handling module for node",
5+
"version": "2.0.0",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/Muscula/nodeerrors"
9+
},
10+
"private": false,
11+
"main": "./lib/nodeerrors.js",
12+
"engines": {
13+
"node": ">=0.6.20",
14+
"npm": ">=1.1.9"
15+
},
16+
"dependencies": {
17+
"underscore": "~1.3.1",
18+
"node-uuid": "~1.4.0"
19+
},
20+
"scripts": {
21+
"test": "node ./bin/runTests.js"
22+
},
23+
"devDependencies": {
24+
"mocha": "",
25+
"chai": "",
26+
"sinon": "",
27+
"sinon-chai": "",
28+
"jshint": "",
29+
"requiremock": ">=1.3.3",
30+
"request": ""
31+
},
32+
"readmeFilename": "readme.md",
33+
"gitHead": "985c718ebf69fc91205c6c40d0a46ce49c717f2b",
34+
"bin": {
35+
"nodeerrors": "runTests.js"
36+
},
37+
"directories": {
38+
"test": "test"
39+
},
40+
"keywords": [
41+
"error",
42+
"handling"
43+
],
44+
"license": "APACHE 2.0"
3245
}

readme.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@ Installation
99
npm install nodeerrors
1010
```
1111

12-
NOTE: Not for use in modules
13-
----------------------------
14-
The way the pars function works, and the way the .errors configuration is read, means you should not use the
15-
nodeerros module in node modules. For now only use it in your main application.
16-
17-
Support for use in modules is on the to-do list.
18-
19-
2012
Specifying you own errors
2113
-------------------------
2214
You specify your own error types by adding the file ```.errors.js``` in the root folder of your project or in
@@ -88,7 +80,7 @@ function (err, data){
8880
The ```errorObject``` variable will now contain
8981
```javascript
9082
{
91-
"name": "propertyNotDefined",
83+
"code": "propertyNotDefined",
9284
"http": 400,
9385
"propertyName": "someProperty",
9486
"message": "The property named \"someProperty\" should be defined",
@@ -135,7 +127,7 @@ function (err, data){
135127
The ```err``` variable will now contain:
136128
```json
137129
{
138-
"name": "propertyNotDefined",
130+
"code": "propertyNotDefined",
139131
"http": 400,
140132
"propertyName": "someProperty",
141133
"message": "The property named \"someProperty\" should be defined",
@@ -160,7 +152,7 @@ var errorCodes = errors.errorCodes;
160152

161153
function handleDocument(err, document){
162154
if(err){
163-
if(err.name = errorCodes.fileNotFound){
155+
if(err.code = errorCodes.fileNotFound){
164156
return callback(errors.mySpecialError().innerError(err));
165157
}
166158
return callback(err);

test/integration/.errors.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
"notUnique":{
3+
message:"The property \"%s\" is not unique. The value \"%s\" already exists.",
4+
args:["propertyName", "propertyValue"],
5+
http:400
6+
},
7+
"propertyNotDefined":{
8+
message:"The property named \"%s\" should be defined",
9+
args:["propertyName"],
10+
http:400
11+
},
12+
"integration":{
13+
message:"Test",
14+
http:400
15+
}
16+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
"test1":{
3+
message:"My test 1",
4+
http:300
5+
}
6+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
delete require.cache[__filename]; //do not cache in require cache
2+
module.exports = require("../../../../lib/nodeerrors.js");

0 commit comments

Comments
 (0)