Skip to content
This repository was archived by the owner on Jun 16, 2018. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
2b6275b
Added score CRUD routing
idanstark42 Jul 29, 2017
39d9422
Using the scores API in the client
idanstark42 Jul 29, 2017
698c517
Added locking mechanism on scores.json
idanstark42 Jul 29, 2017
d13338c
Now that the page is saved in a cookie, there's no need for the refer…
idanstark42 Jul 22, 2017
bff8e14
Now that the pollSheets is automatic, there's no need for the poll bu…
idanstark42 Jul 22, 2017
42e1d5e
Added angular-local-stroage depedency
idanstark42 Aug 1, 2017
bdaae48
Added the angular-local-storage lib
idanstark42 Aug 1, 2017
1ef02c4
Using angular-storage instead: it's more reliable
idanstark42 Aug 1, 2017
3865c07
Using local storage to save a queue of scoresheet ready to be sent to…
idanstark42 Aug 1, 2017
d5f16d2
Added message to explain about the scoresheet-queue
idanstark42 Aug 1, 2017
54f76df
CR fixes: removed String.format and fixed typos
idanstark42 Aug 1, 2017
b1d0419
Added common library and the ability to access it from both front-end…
idanstark42 Aug 5, 2017
7c2cff7
Moved common to the correct location - where both client and server c…
idanstark42 Aug 8, 2017
b4cf42e
Added scores to commong area
idanstark42 Aug 7, 2017
eb38315
Changed to saving all actions
idanstark42 Aug 8, 2017
9e4adf6
Added saving other actions as well
idanstark42 Aug 8, 2017
5b99c53
Finished big migration towards multi-service core. There are some bug…
idanstark42 Aug 8, 2017
c54e452
Fixed some bugs: rankings now works
idanstark42 Aug 8, 2017
ef1d2dc
Removed old common library - it became angular services
idanstark42 Aug 9, 2017
cf44e67
Little bugfix
idanstark42 Aug 9, 2017
f95e5be
Removed common library
idanstark42 Aug 9, 2017
ca9a558
Showing only existing rankings in the rankings view
idanstark42 Aug 9, 2017
4f99d87
working scoresheet insertion
idanstark42 Aug 9, 2017
59c3b4f
Fixed some bugs - now the scores update accordingly
idanstark42 Aug 9, 2017
74e85cc
Added listening funciton to the module
idanstark42 Aug 9, 2017
e85c1da
Cleaning after scores remodeling mess: now it works
idanstark42 Aug 9, 2017
4d36900
It's better to splice an array!
idanstark42 Aug 9, 2017
288f373
Added sync between clients
idanstark42 Aug 9, 2017
d9fdc9c
Merge branch 'master' into referees-2018/scores_sync
idanstark42 Aug 9, 2017
7d81136
Removing server module for common - we don't need it anymore
idanstark42 Aug 9, 2017
2677a21
self CR fixes
idanstark42 Aug 9, 2017
951f56e
Merge branch 'master' into referees-2018/scores_sync
idanstark42 Aug 9, 2017
c167b25
New version of independence - it does all of the work
idanstark42 Aug 9, 2017
f84b4c1
Moved the grouping funcitons into a seperate service
idanstark42 Aug 16, 2017
807e3da
Removed unused function
idanstark42 Aug 16, 2017
73bbe41
New id only if there isn't an existing one
idanstark42 Aug 16, 2017
f4cbc7d
comments
idanstark42 Aug 16, 2017
9f93fb7
correct rank comparation
idanstark42 Aug 16, 2017
d61db34
no special values for now: there is no use for them at this time
idanstark42 Aug 16, 2017
420028b
removed rankings EMPTY constant
idanstark42 Aug 16, 2017
922d10f
Using a for loop: it's more readable
idanstark42 Aug 16, 2017
2a3166a
Split into several more readable variables
idanstark42 Aug 16, 2017
1b572c7
Using score comparation
idanstark42 Aug 16, 2017
6fa085d
Changed the changeScores function according to the CR comments
idanstark42 Aug 16, 2017
706d549
Changed the order of the files in the creation function
idanstark42 Aug 16, 2017
1b760ab
Added error when score is not found
idanstark42 Aug 16, 2017
ae1d1bc
better replacing in the array
idanstark42 Aug 16, 2017
76f21e8
Changed utils.sendError to be more easily usable
idanstark42 Aug 16, 2017
fae6d59
Added angular-storage dependency to tests
idanstark42 Aug 17, 2017
2290e4f
Fixed syntax errors
idanstark42 Aug 17, 2017
ad85d83
UT pass
idanstark42 Aug 18, 2017
6494876
Added ;
idanstark42 Aug 18, 2017
f4b8fe2
Changed sorting icons to a material-icons versions in ranking
ThinkRedstone Aug 20, 2017
8259226
Added special case for travis env
idanstark42 Aug 20, 2017
f839d8f
Conflict of variables
idanstark42 Aug 20, 2017
388b740
Changed karma config
idanstark42 Aug 20, 2017
2279f1e
Run on newest node version
idanstark42 Aug 20, 2017
882e55b
Not using chromium
idanstark42 Aug 20, 2017
6ed40e9
Trusty
idanstark42 Aug 20, 2017
54a260c
expiriment
idanstark42 Aug 20, 2017
104a43c
No more short cuts
idanstark42 Aug 20, 2017
01da877
Removed this module dependency: it might be ruining the build
idanstark42 Aug 20, 2017
a2dc1af
Added missing module
idanstark42 Aug 20, 2017
0e58cb1
No comma
idanstark42 Aug 20, 2017
645d36e
Added current score to the appbar
ThinkRedstone Aug 22, 2017
1d11dbb
Revert "Changed sorting icons to a material-icons versions in ranking"
ThinkRedstone Aug 22, 2017
ad95803
Added rankings UT
idanstark42 Aug 23, 2017
6321439
Resolved error with object comparation in rankings sepcs
idanstark42 Aug 23, 2017
7dbd14b
Better calc
idanstark42 Aug 24, 2017
ef8f73a
Added specs for the factory
idanstark42 Aug 24, 2017
3eeb0cb
Added the spces
idanstark42 Aug 24, 2017
6982314
Renamed session to ng-session to follow convention
idanstark42 Aug 24, 2017
384a931
create http mock
idanstark42 Aug 25, 2017
aea9595
Added session specs
idanstark42 Aug 25, 2017
1f03d5b
session sepcs fixes
idanstark42 Aug 25, 2017
65ae723
Added ng-independence UT
idanstark42 Aug 25, 2017
f174bf0
Added score validation UT
idanstark42 Aug 25, 2017
cabc6f3
Added ng-scores UT
idanstark42 Aug 25, 2017
b1bf445
Remove unneeded tests
idanstark42 Aug 25, 2017
8f08c0a
loading before clearing in scores scpecs
idanstark42 Aug 26, 2017
0270c27
tests change
idanstark42 Aug 26, 2017
6b303f5
better tests
idanstark42 Aug 26, 2017
6dd369a
removed unneeded test
idanstark42 Aug 26, 2017
6741200
Merge pull request #5 from ThinkRedstone/show-score
idanstark42 Aug 26, 2017
494151d
Merge branch 'master' of https://github.com/FirstLegoLeagueIL/fllscor…
idanstark42 Aug 26, 2017
068ec57
Merge pull request #9 from idanstark42/referees-2018/scores_sync
idanstark42 Aug 26, 2017
6549406
Fixed the undefined error in main and session
idanstark42 Aug 26, 2017
3520b83
Fixed the tests according to the hotfix
idanstark42 Aug 26, 2017
23eac34
Merge pull request #10 from idanstark42/hotfix
idanstark42 Aug 26, 2017
8b3b684
fixed pages bug after session renaming
idanstark42 Aug 26, 2017
924ecf2
displaying rankings correctly
idanstark42 Aug 26, 2017
067a926
Fixed the CSV export in rankings
idanstark42 Aug 26, 2017
d06641f
Fixed lockfile promise error
idanstark42 Aug 26, 2017
ceef2ef
Fixed duplicate score error message
idanstark42 Aug 26, 2017
1a9db9c
Indpendence promise should pass on the response from the server
idanstark42 Aug 26, 2017
f46345e
Fixed error message on scoresheet
idanstark42 Aug 26, 2017
b9e8b29
Merge pull request #11 from idanstark42/bugfixes
idanstark42 Aug 26, 2017
c4d8d26
Fixed error dealing in scores andin general
idanstark42 Aug 26, 2017
0bb4427
Removed backward compatibility: working only with ids from now on
idanstark42 Aug 26, 2017
e70f572
UT
idanstark42 Aug 26, 2017
d053b27
CR fixes
idanstark42 Aug 27, 2017
8307c42
Added ranking filter
idanstark42 Aug 27, 2017
2cc771a
Merge branch 'server_exceptions' into referees-2018/scores_sync
idanstark42 Aug 27, 2017
3b5dc2b
Merge branch 'master' of https://github.com/FirstLegoLeague/fllscorin…
idanstark42 Aug 28, 2017
45c5b7b
CR changes
idanstark42 Aug 28, 2017
e487f95
Fixed some bugs with the lock module
idanstark42 Aug 28, 2017
cd2503c
Removed unused statement
idanstark42 Aug 28, 2017
cd56007
prettifing code
idanstark42 Aug 28, 2017
e72cde7
Removed this mock: it's a part of the unit and should be tested as well
idanstark42 Aug 28, 2017
ff4592b
Using catch instead of second then argument
idanstark42 Aug 28, 2017
ba18987
Added clearing the localStorage between runs
idanstark42 Aug 28, 2017
5ac279f
Skipping pendingActions tests
idanstark42 Aug 28, 2017
ac25467
Extracted score entry from scoresheet
idanstark42 Aug 28, 2017
3d128dc
Added backward comaptibility in scores.json versions
idanstark42 Aug 28, 2017
47cc7cd
Made it work
idanstark42 Aug 28, 2017
777d7ee
Explicit call to .init
idanstark42 Aug 28, 2017
b5d5c8a
Running backward compatibility only on server start
idanstark42 Aug 28, 2017
d6199bb
Ignoring existing file error in locks
idanstark42 Aug 28, 2017
10752c3
Adding id to scores that don't have it on creation
idanstark42 Aug 28, 2017
19aa792
Added deprecation warning to scores json
idanstark42 Aug 29, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ src/components/*/*
!src/components/angular-touch/angular*.js
!src/components/angular-touch/angular*.map
!src/components/angular-bootstrap/*.js
!src/components/angular-storage/*.js

!src/components/bootstrap-css/css
!src/components/bootstrap-css/img
Expand Down
8 changes: 7 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
language: node_js
dist: trusty
sudo: true
node_js:
- 0.10
- "stable"
before_install:
- "npm i -g bower karma-cli"
before_script:
- export CHROME_BIN=/usr/bin/google-chrome
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sudo apt-get install -y libappindicator1 fonts-liberation
- wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- sudo dpkg -i google-chrome*.deb
after_script:
- ls ./coverage
- 'npm install coveralls@2.10.0 && cat "./coverage/Firefox 31.0.0 (Linux)/lcov.info" | coveralls'
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"dependencies": {
"angular": "~1.2.20",
"angular-bootstrap": "~0.11.0",
"angular-local-storage": "~0.6.0",
"angular-mocks": "~1.2.20",
"angular-sanitize": "~1.3.3",
"angular-touch": "~1.3.4",
Expand Down
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = function(config) {
'src/components/jquery/jquery.min.js',
'src/components/angular/angular.min.js',
'src/components/angular-mocks/angular-mocks.js',
'src/components/angular-storage/angular-storage.js',
'src/components/q/q.js',
'src/components/idbwrapper/idbstore.js',
'spec/helpers/*.js',
Expand Down
2 changes: 1 addition & 1 deletion localserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ routers.forEach(function(router) {

app.listen(args.port, function() {
console.log('Listening on port ', args.port);
console.log('open browser to http://localhost:{0}/'.format(args.port));
console.log(`open browser to http://localhost:${args.port}/`);
});
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"start": "node localserver",
"test": "./node_modules/.bin/karma start --single-run --browsers Firefox --reporters dots,coverage"
"test": "./node_modules/.bin/karma start --single-run --reporters dots,coverage"
},
"repository": {
"type": "git",
Expand All @@ -30,6 +30,7 @@
},
"dependencies": {
"basic-auth-connect": "~1.0.0",
"lockfile": "~1.0.3",
"uuid": "^3.1.0",
"express": "^4.10.4",
"express-session": "^1.5.0",
Expand Down
2 changes: 1 addition & 1 deletion server_modules/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exports.route = function(app) {

//get challenges over xhr, for hosted service
app.get('/challenge/:year', function(req, res) {
var file = fileSystem.resolve('challenges/js/{0}.js'.format(req.params.year));
var file = fileSystem.resolve(`challenges/js/${req.params.year}.js`);

res.header('Content-Type','text/plain');
res.sendFile(file);
Expand Down
23 changes: 7 additions & 16 deletions server_modules/file_system.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ exports.readFile = function(file) {
if (exists) {
resolve(exists);
} else {
log.error("file not found {0}".format(file));
reject({
status: 404,
message: 'file not found'
Expand All @@ -42,7 +41,6 @@ exports.readFile = function(file) {
});
}).then(function() {
return Q.nfcall(fs.readFile, file, "utf-8").catch(function(e) {
log.error("error reading file {0}".format(file));
throw new Error({
status: 500,
message: 'error reading file'
Expand Down Expand Up @@ -77,24 +75,21 @@ exports.route = function(app) {
var file = exports.getDataFilePath(req.params[0]);
fs.stat(file, function(err, stat) {
if (err) {
log.error("file not found {0}".format(file));
res.status(404).send('file not found');
utils.sendError(res, { status: 404, message: `file not found ${file}` })
return;
}
if (stat.isFile()) {
fs.readFile(file, function(err, data) {
if (err) {
log.error("error reading file {0}".format(file));
res.status(500).send('error reading file');
utils.sendError(res, { status: 500, message: `error reading file ${file}` })
return;
}
res.send(data);
});
} else if (stat.isDirectory()) {
fs.readdir(file, function(err, filenames) {
if (err) {
log.error("error reading dir {0}".format(file));
res.status(500).send('error reading dir');
utils.sendError(res, { status: 500, message: `error reading dir ${file}` })
return;
}
// FIXME: this doesn't work for filenames containing
Expand All @@ -103,15 +98,13 @@ exports.route = function(app) {
return name.indexOf("\n") >= 0;
});
if (hasNewline) {
log.error("invalid filename(s) {0}".format(filenames.join(', ')));
res.status(500).send('invalid filename(s)');
utils.sendError(res, { status: 500, message: `invalid filename(s) ${filenames.join(', ')}` })
return;
}
res.send(filenames.join('\n'));
});
} else {
log.error("error reading file {0}".format(file));
res.status(500).send('error reading file');
utils.sendError(res, { status: 500, message: `error reading file ${file}` })
return;
}
});
Expand All @@ -123,8 +116,7 @@ exports.route = function(app) {
exports.writeFile(file, req.body).then(function() {
res.status(200).end();
}).catch(function(err) {
log.error("error writing file {0}".format(err));
res.status(500).send('error writing file');
utils.sendError(res, { status: 500, message: `error writing file ${file}` })
});
});

Expand All @@ -133,8 +125,7 @@ exports.route = function(app) {
var file = exports.getDataFilePath(req.params[0]);
fs.unlink(file, function(err) {
if (err) {
log.error("error removing file {0}".format(err));
res.status(500).send('error removing file');
utils.sendError(res, { status: 500, message: `error removing file ${file}` })
}
res.status(200).end();
});
Expand Down
33 changes: 33 additions & 0 deletions server_modules/lock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//This module wraps lockfile with promises.
var lockfile = require('lockfile');

module.exports = function(filename, options) {
this.filename = filename;
this.options = options || {};

this.lock = function() {
var self = this;

return new Promise(function(resolve, reject) {
lockfile.lock('scores.json.lock', self.options, function(err) {
if(err !err.startsWith('EEXIST')) {
reject(err);
}

resolve();
});
});
};

this.unlock = function() {
return new Promise(function(resolve, reject) {
lockfile.unlock('scores.json.lock', function(err) {
if(err && !err.startsWith('EEXIST')){
reject(err);
}

resolve();
});
});
};
}
2 changes: 1 addition & 1 deletion server_modules/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exports.middleware = function(req, res, next) {

req.log = exports.log;

req.log.debug('Starting {0} {1}'.format(req.method, req.originalUrl));
req.log.debug(`Starting ${req.method} ${req.originalUrl}`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly unrelated to this PR, but instead of (or in addition to) logging the start of a request, it would be helpful to log the completion of a request because that can include the reponse code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I do that? Is there a way to call a function after the routing functions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I looked it up, and it is possible. You just need to add next() calls to all the routing functions. It will be a separate PR though


next();

Expand Down
123 changes: 121 additions & 2 deletions server_modules/scores.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
var Lock = require('./lock');
var utils = require('./utils');
var fileSystem = require('./file_system');
var log = require('./log').log;
var Q = require('q');
var id = require('uuid/v4');

function filterPublished(score) {
return score.published;
Expand All @@ -15,6 +18,45 @@ function reduceToMap(key) {
}
}

/**
* Atomically change scores file.
* Action callback is called with the current contents of the scores file, and is expected
* to return the new contents (or a Promise for it).
* A lock is acquired and held during the entire operation.
* @param action Callback that receives current scores.json object, must return new contents (or Promise for it)
* @return Promise for updated scores object
*/
function changeScores(action) {
var path = fileSystem.getDataFilePath('scores.json');
var lock = new Lock('scores.json.lock', { retries: 5, retryWait: 100 });

console.log(lock.options);

return lock.lock()
.then(() => fileSystem.readJsonFile(path))
.catch((err) => { //Ignoring all file not found errors, and just returning empty scores.json
console.log("catching");
if(err.message === 'file not found') {
console.log("hells yeah!");
return { version:3, scores: [] };
} else {
console.log("ho no! " + err.message);
throw err;
}
})
.then(action)
.then(scores => {
return fileSystem.writeFile(path, JSON.stringify(scores))
.then(() => {
return lock.unlock();
}).catch((err) => {
return lock.unlock();
}).then(function() {
return scores;
});
});
}

exports.route = function(app) {

//get all, grouped by round
Expand All @@ -32,7 +74,7 @@ exports.route = function(app) {
return rounds;
},{});
res.json(published);
}).catch(utils.sendError(res)).done();
}).catch(err => utils.sendError(res, err)).done();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better, but still tricky in that you return raw server errors. (minor thing for now)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very well, since I'm swamp, I think we can leave that for later on

});

//get scores by round
Expand All @@ -44,7 +86,84 @@ exports.route = function(app) {
return score.published && score.round === round;
});
res.json(scoresForRound);
}).catch(utils.sendError(res)).done();
}).catch(err => utils.sendError(res, err)).done();
});

//save a new score
app.post('/scores/create',function(req,res) {
var body = JSON.parse(req.body);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when body is invalid JSON?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An error is thrown, and sent to the client

var scoresheet = body.scoresheet;
var score = body.score;

fileSystem.writeFile(fileSystem.getDataFilePath("scoresheets/" + score.file), req.body)
.then(changeScores(function(result) {
if(typeof(score.id) === 'undefined') {
score.id = id();
}
result.scores.push(score);
return result;
}))
.then(function(scores) {
res.json(scores).end();
}).catch(err => utils.sendError(res, err)).done();

});

//delete a score at an id
app.post('/scores/delete/:id',function(req,res) {
changeScores(function(result) {
var index = result.scores.findIndex((score) => score.id === req.params.id);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the id isn't found? (e.g. conficting edit actions)
Return a more appropriate error to the client than a crash?

if(index === -1) {
throw new Error(`Could not find score with id ${req.params.id}`);
}
result.scores.splice(index, 1);
return result;
}).then(function(scores) {
res.json(scores).end();
}).catch(err => utils.sendError(res, err)).done();
});

//edit a score at an id
app.post('/scores/update/:id',function(req,res) {
var score = JSON.parse(req.body);
changeScores(function(result) {
var index = result.scores.findIndex((score) => score.id === req.params.id);
if(index === -1) {
throw new Error(`Could not find score with id ${req.params.id}`);
}
result.scores[index] = score;
return result;
}).then(function(scores) {
res.json(scores).end();
}).catch(err => utils.sendError(res, err)).done();
});


};


// For backward compatibility

changeScores(function(scores) {
if(typeof(scores.version) === 'undefined') {
log.warn('Deprecated scores version. Updating to version 3.')
scores.forEach(score => score.id = id())
return {
version: 3,
scores: scores
}

} else if(scores.version === 3) {
return scores;

} else if(scores.version === 2) {
log.warn('Deprecated scores version. Updating to version 3.');
scores.scores.forEach(score => score.id = id())
scores.version = 3;
return scores;

} else {
throw new Error('Unkown scores version');
}

});
4 changes: 2 additions & 2 deletions server_modules/teams.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ exports.route = function(app) {
app.get('/teams',function(req,res) {
fileSystem.readJsonFile(fileSystem.getDataFilePath('teams.json')).then(function(result) {
res.json(result);
}).catch(utils.sendError(res)).done();
}).catch(err => utils.sendError(res, err)).done();
});

app.get('/teams/:nr',function(req,res) {
Expand All @@ -16,7 +16,7 @@ exports.route = function(app) {
return team.number == req.params.nr;
})[0];
res.json(team);
}).catch(utils.sendError(res)).done();
}).catch(err => utils.sendError(res, err)).done();
});

};
27 changes: 11 additions & 16 deletions server_modules/utils.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
exports.root = __dirname + '/../';

exports.sendError = function(res) {
return function(err) {
res.status(err.status).send(err.message);
}
}

if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] !== 'undefined' ? args[number] : match;
});
};
}
var log = require('./log').log;

exports.root = __dirname + '/../';

exports.sendError = function(res, err) {
var status = err.status || 500;
var message = err.message || "Internal server error"

log.error(message);
res.status(status).send(message);
}
Loading