From 7dea45ab1974d380919745c2f84b67f23efb7d32 Mon Sep 17 00:00:00 2001 From: Aiko Mastboom Date: Wed, 1 Jul 2015 17:04:10 +0200 Subject: [PATCH] js checks complient/ code formatter --- .gitignore | 2 + .jshintrc | 102 ++++++++++++++++++++++++ lib/handlers.js | 16 ++-- lib/helpers.js | 18 ++--- lib/importer.js | 85 ++++++++++---------- lib/markers.js | 62 +++++++-------- lib/mongoData.js | 139 +++++++++++++++++--------------- lib/preview.js | 142 ++++++++++++++++----------------- lib/responder.js | 3 +- lib/routes.js | 64 +++++++-------- lib/share.js | 14 ++-- lib/shareHandlers.js | 75 ++++++++++-------- package.json | 64 +++++++-------- server.js | 175 ++++++++++++++++++++++++----------------- test/test.helpers.js | 66 ++++++++-------- test/test.mongoData.js | 58 ++++++++------ 16 files changed, 628 insertions(+), 457 deletions(-) create mode 100644 .jshintrc diff --git a/.gitignore b/.gitignore index 73c490d..8c2830c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ fleet.json *.log .fseventsd .TemporaryItems +node_modules/ +doc/ diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..a920c65 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,102 @@ +{ + // JSHint Default Configuration File (as on JSHint website) + // See http://jshint.com/docs/ for more details + + "maxerr" : 10, // {int} Maximum error before stopping + + // Enforcing + "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) + "camelcase" : false, // true: Identifiers must be in camelCase + "curly" : true, // true: Require {} for every new block or scope + "eqeqeq" : true, // true: Require triple equals (===) for comparison + "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() + "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` + "indent" : 4, // {int} Number of spaces to use for indentation + "latedef" : true, // true: Require variables/functions to be defined before being used + "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` + "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` + "noempty" : true, // true: Prohibit use of empty blocks + "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) + "plusplus" : false, // true: Prohibit use of `++` & `--` + "quotmark" : true, // Quotation mark consistency: + // false : do nothing (default) + // true : ensure whatever is used is consistent + // "single" : require single quotes + // "double" : require double quotes + "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) + "unused" : true, // true: Require all defined variables be used + "strict" : true, // true: Requires all functions run in ES5 Strict Mode + "trailing" : true, // true: Prohibit trailing whitespaces + "maxparams" : false, // {int} Max number of formal params allowed per function + "maxdepth" : false, // {int} Max depth of nested blocks (within functions) + "maxstatements" : false, // {int} Max number statements per function + "maxcomplexity" : false, // {int} Max cyclomatic complexity per function + "maxlen" : false, // {int} Max number of characters per line + + // Relaxing + "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) + "boss" : false, // true: Tolerate assignments where comparisons would be expected + "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. + "eqnull" : true, // true: Tolerate use of `== null` + "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) + "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) + "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) + // (ex: `for each`, multiple try/catch, function expression…) + "evil" : false, // true: Tolerate use of `eval` and `new Function()` + "expr" : true, // true: Tolerate `ExpressionStatement` as Programs + "funcscope" : false, // true: Tolerate defining variables inside control statements" + "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') + "iterator" : false, // true: Tolerate using the `__iterator__` property + "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block + "laxbreak" : false, // true: Tolerate possibly unsafe line breakings + "laxcomma" : false, // true: Tolerate comma-first style coding + "loopfunc" : false, // true: Tolerate functions being defined in loops + "multistr" : false, // true: Tolerate multi-line strings + "proto" : false, // true: Tolerate using the `__proto__` property + "scripturl" : false, // true: Tolerate script-targeted URLs + "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment + "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` + "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation + "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` + "validthis" : false, // true: Tolerate using this in a non-constructor function + + // Environments + "browser" : true, // Web Browser (window, document, etc) + "couch" : false, // CouchDB + "devel" : true, // Development/debugging (alert, confirm, etc) + "dojo" : false, // Dojo Toolkit + "jquery" : false, // jQuery + "mootools" : false, // MooTools + "node" : true, // Node.js + "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) + "prototypejs" : false, // Prototype and Scriptaculous + "rhino" : false, // Rhino + "worker" : false, // Web Workers + "wsh" : false, // Windows Scripting Host + "yui" : false, // Yahoo User Interface + + // Legacy + "nomen" : false, // true: Prohibit dangling `_` in variables + "onevar" : false, // true: Allow only one `var` statement per function + "passfail" : false, // true: Stop on first error + "white" : false, // true: Check against strict whitespace and indentation rules + + // Custom Globals + "globals" : { + + // RequireJS + "define": true, + "requirejs": true, + + // mocha + "describe": true, + "beforeEach": true, + "afterEach": true, + "before": true, + "after": true, + "it": true, + + //chai + "expect": true + } +} diff --git a/lib/handlers.js b/lib/handlers.js index 371e522..301c075 100644 --- a/lib/handlers.js +++ b/lib/handlers.js @@ -1,26 +1,26 @@ +'use strict'; module.exports = function (mongoDataInstance, previewInstance, importerInstance) { - "use strict"; function getAttribute(options, callback) { - mongoDataInstance.getMongoAttribute(options, callback); + return mongoDataInstance.getMongoAttribute(options, callback); } function getContent(options, callback) { - mongoDataInstance.getMongoContent(options, callback); + return mongoDataInstance.getMongoContent(options, callback); } function getPreviewHTML(html, options, callback) { - previewInstance.getPreviewHTML(html, options, callback); + return previewInstance.getPreviewHTML(html, options, callback); } function importer(doc, options, callback) { - importerInstance.importer(doc, options, callback); + return importerInstance.importer(doc, options, callback); } return { - getAttribute: getAttribute, - getContent: getContent, + getAttribute: getAttribute, + getContent: getContent, getPreviewHTML: getPreviewHTML, - importer: importer + importer: importer }; }; diff --git a/lib/helpers.js b/lib/helpers.js index 7e30362..a0d10f2 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -1,12 +1,12 @@ +'use strict'; var when = require('when'); -var _ = require('underscore'); +var _ = require('underscore'); module.exports = function (markers) { - "use strict"; function replace(text, marker, getReplacement, once) { var deferred = when.defer(); - var regExp = new RegExp(markers.prefix + marker + markers.postfix, 'gmi'); - var matches = text && text.match && text.match(regExp); + var regExp = new RegExp(markers.prefix + marker + markers.postfix, 'gmi'); + var matches = text && text.match && text.match(regExp); if (matches) { if (once) { matches = [matches[0]]; @@ -20,7 +20,7 @@ module.exports = function (markers) { deferred2.reject(err); } else { var replace_result = { - regExp: replacement.regExp || regExp, + regExp: replacement.regExp || regExp, replacement: replacement.value }; deferred2.resolve(replace_result); @@ -51,18 +51,18 @@ module.exports = function (markers) { }); }); } catch (e) { - return callback(e); + return callback && callback(e); } - return callback(null, text); + return callback && callback(null, text); }, function onFailure(err) { - return callback(err); + return callback && callback(err); } ); } return { - replace: replace, + replace: replace, handTextManipulation: handTextManipulation }; }; diff --git a/lib/importer.js b/lib/importer.js index f321938..c549689 100644 --- a/lib/importer.js +++ b/lib/importer.js @@ -1,12 +1,11 @@ +'use strict'; var when = require('when'); -var _ = require('underscore'); +var _ = require('underscore'); var path = require('path'); -var fs = require('fs'); +var fs = require('fs'); module.exports = function (config, mongoInstance, helpers, markers) { - "use strict"; - var replaceMarkers; function handleImportMarkers(doc, options, callback) { @@ -18,28 +17,28 @@ module.exports = function (config, mongoInstance, helpers, markers) { return new_text; } - helpers.handTextManipulation(doc, + return helpers.handTextManipulation(doc, promises, handler, callback ); } - var import_leftovers_tag = markers.import_leftovers_tag; + var import_leftovers_tag = markers.import_leftovers_tag; var import_leftovers_regexp = markers.import_leftovers_regexp; function importer(doc, options, cb) { var promises = helpers.replace(doc, import_leftovers_tag, function getReplacement(result, callback) { - var parts = import_leftovers_regexp.exec(result); + var parts = import_leftovers_regexp.exec(result); var context = { collection: parts[1], - name: parts[2], - attribute: parts[3] + name: parts[2], + attribute: parts[3] }; return callback(null, { regExp: new RegExp(result, 'gmi'), - value: context + value: context }); }, // there can be only one import_leftovers @@ -50,33 +49,33 @@ module.exports = function (config, mongoInstance, helpers, markers) { handleImportMarkers(doc, options, function handleLeftover(err, remainder) { if (err) { config.error && config.error('ERR importer.importer handleImportMarkers', err); - return cb(err); + return cb && cb(err); } if (leftover) { return mongoInstance.ensureContent(leftover.replacement, function parent(err, parent_result) { if (err) { config.error && config.error('ERR importer.importer ensureContent', err); - return cb(err); + return cb && cb(err); } - leftover.replacement.query = { _id: parent_result._id }; + leftover.replacement.query = {_id: parent_result._id}; - remainder = remainder.replace(leftover.regExp, ""); + remainder = remainder.replace(leftover.regExp, ''); return mongoInstance.setMongoAttribute(remainder, leftover.replacement, function savedAttribute(err) { if (err) { config.error && config.error('ERR importer.importer setMongoAttribute', err); - return cb(err); + return cb && cb(err); } - return cb(null, remainder); + return cb && cb(null, remainder); }); }); } config.debug && config.debug('no import_leftover tag found'); - return cb(null, remainder); + return cb && cb(null, remainder); }); }, function onFailure(err) { config.error && config.error('ERR importer.importer onFailure', err); - return cb(err); + return cb && cb(err); } ); } @@ -86,23 +85,23 @@ module.exports = function (config, mongoInstance, helpers, markers) { return mongoInstance.ensureContent(context, function parent(err, parent_result) { if (err) { config.error && config.error('ERR importer.importer ensureContent', err); - return callback(err); + return callback && callback(err); } function replaceWithEmptyContent(err) { var replacement = { regExp: result, - value: "" + value: '' }; - return callback(err, replacement); + return callback && callback(err, replacement); } - if (context.attribute === "json") { - var data = null; + if (context.attribute === 'json') { + var data = null; try { data = JSON.parse(remainder); } catch (error) { config.error && config.error('ERR importer.replaceMarkers JSON.parse(remainder)', remainder, error); - return callback(error); + return callback && callback(error); } if (data._id) { delete data._id; @@ -112,31 +111,31 @@ module.exports = function (config, mongoInstance, helpers, markers) { return mongoInstance.setMongoContent(parent_result, context, function (err) { if (err) { config.error && config.error('ERR importer.importRemainder setMongoContent', err); - return callback(err); + return callback && callback(err); } var documentId = 'json:' + context.collection + ':' + context.name; - var keys = _.keys(parent_result); // reset all attributes; + var keys = _.keys(parent_result); // reset all attributes; return mongoInstance.updateShareDocument(documentId, parent_result, keys, function () { return replaceWithEmptyContent(null); }); }); } - context.query = { _id: parent_result._id }; + context.query = {_id: parent_result._id}; return mongoInstance.setMongoAttribute(remainder, context, function savedAttribute(err) { if (err) { config.error && config.error('ERR2 importer.importer setMongoAttribute', err); - return callback(err); + return callback && callback(err); } return replaceWithEmptyContent(null); }); }); } - var import_tag = markers.import_tag; - var import_regexp = markers.import_regexp; + var import_tag = markers.import_tag; + var import_regexp = markers.import_regexp; var import_strip_regexp = markers.import_strip_regexp; - var import_file_tag = markers.import_file_tag; + var import_file_tag = markers.import_file_tag; var import_file_regexp = markers.import_file_regexp; replaceMarkers = function (doc, options) { @@ -144,19 +143,19 @@ module.exports = function (config, mongoInstance, helpers, markers) { promises.push( helpers.replace(doc, import_tag, function handleImportMarker(result, callback) { - var parts = import_regexp.exec(result); - var context = { + var parts = import_regexp.exec(result); + var context = { collection: parts[1], - name: parts[2], - attribute: parts[3] + name: parts[2], + attribute: parts[3] }; var striped_parts = import_strip_regexp.exec(parts[4]); - var sub_doc = striped_parts[1]; + var sub_doc = striped_parts[1]; handleImportMarkers(sub_doc, options, function handleLeftover(err, remainder) { if (err) { config.error && config.error('ERR importer.replaceMarkers import_content_marker', err); - return callback(err); + return callback && callback(err); } return importRemainder(context, result, remainder, callback); }); @@ -166,23 +165,23 @@ module.exports = function (config, mongoInstance, helpers, markers) { promises.push( helpers.replace(doc, import_file_tag, function handleImportFileMarker(result, callback) { - var parts = import_file_regexp.exec(result); + var parts = import_file_regexp.exec(result); var filename = path.resolve(config.statics.importer_path, parts[1]); - var context = { + var context = { collection: parts[2], - name: parts[3], - attribute: parts[4] + name: parts[3], + attribute: parts[4] }; fs.readFile(filename, 'utf-8', function handleFileContent(err, sub_doc) { if (err) { config.error && config.error('ERR importer.replaceMarkers readFile', err); - return callback(err); + return callback && callback(err); } // process with leftover marker support return importer(sub_doc, context, function handleLeftover(err, remainder) { if (err) { config.error && config.error('ERR importer.replaceMarkers importer', err); - return callback(err); + return callback && callback(err); } return importRemainder(context, result, remainder, callback); }); diff --git a/lib/markers.js b/lib/markers.js index 269a6a7..45bcc24 100644 --- a/lib/markers.js +++ b/lib/markers.js @@ -1,23 +1,23 @@ +'use strict'; module.exports = function markers(config) { - "use strict"; - var marker_prefix = ''; // Preview markers - var script_tag = 'script__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var script_tag = 'script__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var script_regexp = new RegExp(marker_prefix + script_tag + marker_postfix); - var style_tag = 'style__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var style_tag = 'style__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var style_regexp = new RegExp(marker_prefix + style_tag + marker_postfix); - var less_tag = 'less__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var less_tag = 'less__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var less_regexp = new RegExp(marker_prefix + less_tag + marker_postfix); - var template_tag = 'template__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)__context__([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var template_tag = 'template__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)__context__([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var template_regexp = new RegExp(marker_prefix + template_tag + marker_postfix); - var markdown_tag = 'markdown__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var markdown_tag = 'markdown__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var markdown_regexp = new RegExp(marker_prefix + markdown_tag + marker_postfix); // remove_tag is greedy, so we can do multiple removes on one page. @@ -25,16 +25,16 @@ module.exports = function markers(config) { //var remove_regexp = new RegExp(remove_tag); // Importer markers - var import_leftovers_tag = 'import_leftovers__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var import_leftovers_tag = 'import_leftovers__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var import_leftovers_regexp = new RegExp(marker_prefix + import_leftovers_tag + marker_postfix); // import tag is non greedy on purpose, you can only import content into 1 object, // repeating the same tag will result in content overwriting each other. - var import_tag = 'import__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)_([\\w\\W]*)_end_import__\\1_\\2_\\3'; - var import_regexp = new RegExp(marker_prefix + import_tag + marker_postfix); + var import_tag = 'import__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)_([\\w\\W]*)_end_import__\\1_\\2_\\3'; + var import_regexp = new RegExp(marker_prefix + import_tag + marker_postfix); var import_strip_regexp = new RegExp(marker_postfix + '([\\w\\W]*)' + marker_prefix); - var import_file_tag = 'import_file__([A-Za-z0-9.\/]+)__into__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; + var import_file_tag = 'import_file__([A-Za-z0-9.\/]+)__into__([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z0-9]+)'; var import_file_regexp = new RegExp(marker_prefix + import_file_tag + marker_postfix); @@ -45,27 +45,27 @@ module.exports = function markers(config) { } return { - prefix: marker_prefix, - postfix: marker_postfix, - createTag: createTag, - script_tag: script_tag, - script_regexp: script_regexp, - style_tag: style_tag, - style_regexp: style_regexp, - less_tag: less_tag, - less_regexp: less_regexp, - template_tag: template_tag, - template_regexp: template_regexp, - markdown_tag: markdown_tag, - markdown_regexp: markdown_regexp, - remove_tag: remove_tag, + prefix: marker_prefix, + postfix: marker_postfix, + createTag: createTag, + script_tag: script_tag, + script_regexp: script_regexp, + style_tag: style_tag, + style_regexp: style_regexp, + less_tag: less_tag, + less_regexp: less_regexp, + template_tag: template_tag, + template_regexp: template_regexp, + markdown_tag: markdown_tag, + markdown_regexp: markdown_regexp, + remove_tag: remove_tag, // remove_regexp:remove_regexp, - import_leftovers_tag: import_leftovers_tag, + import_leftovers_tag: import_leftovers_tag, import_leftovers_regexp: import_leftovers_regexp, - import_tag: import_tag, - import_regexp: import_regexp, - import_strip_regexp: import_strip_regexp, - import_file_tag: import_file_tag, - import_file_regexp: import_file_regexp + import_tag: import_tag, + import_regexp: import_regexp, + import_strip_regexp: import_strip_regexp, + import_file_tag: import_file_tag, + import_file_regexp: import_file_regexp }; }; diff --git a/lib/mongoData.js b/lib/mongoData.js index 5ef3631..3149365 100644 --- a/lib/mongoData.js +++ b/lib/mongoData.js @@ -1,51 +1,51 @@ +'use strict'; var ObjectID = require('mongodb').ObjectID; -var _ = require('underscore'); +var _ = require('underscore'); module.exports = function (config, db, shareModel) { - "use strict"; /* - options: + * options: * collection (mandatory) * query (mandatory) */ function getMongoContent(options, callback) { config.debug && config.debug('getMongoContent options', options); - if ( !options.collection) { + if (!options.collection) { return callback(new Error('Data not found / missing collection')); } return db.collection(options.collection, function collection(err, col) { if (err) { config.error && config.error('ERR2 getMongoContent', err); - return callback(err); + return callback && callback(err); } if (!options.query) { - return callback(new Error('Data not found ' + options.collection + '/ missing query'), null, col); + return callback && callback(new Error('Data not found ' + options.collection + '/ missing query'), null, col); } if (options.query._id && !(options.query._id instanceof Object)) { try { options.query._id = new ObjectID.createFromHexString(options.query._id); } catch (error) { config.error && config.error('ERR3 getMongoContent', error); - return callback(error); + return callback && callback(error); } } return col.findOne(options.query, function foundOne(err, result) { if (err) { config.error && config.error('ERR4 getMongoContent', err); - return callback(err); + return callback && callback(err); } if (!result) { - return callback(new Error('Data not found ' + options.collection + '/' + JSON.stringify(options.query)), null, col); + return callback && callback(new Error('Data not found ' + options.collection + '/' + JSON.stringify(options.query)), null, col); } - return callback(null, result, col); + return callback && callback(null, result, col); }); }); } /* - options: + * options: * collection (mandatory) * query (mandatory) * attribute (mandatory) @@ -55,7 +55,7 @@ module.exports = function (config, db, shareModel) { return getMongoContent(options, function document(err, result) { if (err) { config.error && config.error('ERR1 getMongoAttribute', err); - return callback(err); + return callback && callback(err); } var attribute_options = null; config.debug && config.debug('getMongoAttribute result', result); @@ -64,25 +64,25 @@ module.exports = function (config, db, shareModel) { result[options.attribute].guid) { attribute_options = { collection: options.collection, - query: {_id: result[options.attribute].guid} + query: {_id: result[options.attribute].guid} }; config.debug && config.debug('getMongoAttribute attribute_options', attribute_options); getMongoContent(attribute_options, function attribute(err, attribute_result) { if (err) { config.error && config.error('ERR2 getMongoAttribute', err); - return callback(err); + return callback && callback(err); } config.debug && config.debug('getMongoAttribute attribute_result', attribute_result); - return callback(err, attribute_result); + return callback && callback(err, attribute_result); }); } else { config.debug && config.debug('getMongoAttribute try direct lookup'); attribute_options = { collection: options.collection, - query: { + query: { parent: result._id, - name: result.name + '.' + options.attribute + name: result.name + '.' + options.attribute } }; config.debug && config.debug('getMongoAttribute attribute_options', attribute_options); @@ -90,10 +90,10 @@ module.exports = function (config, db, shareModel) { return getMongoContent(attribute_options, function attribute(err, attribute_result) { if (err) { config.error && config.error('ERR getMongoAttribute', err); - return callback(err); + return callback && callback(err); } config.debug && config.debug('getMongoAttribute direct attribute_result', attribute_result); - return callback(err, attribute_result); + return callback && callback(err, attribute_result); }); } }); @@ -107,11 +107,11 @@ module.exports = function (config, db, shareModel) { collection.save(data, {safe: true}, function (err, result2, result3) { if (err) { config.error && config.error('ERR saveData', err); - return callback(err); + return callback && callback(err); } config.debug && config.debug('saveData saved', data._id, result2, result3); - return callback(null, data, collection); + return callback && callback(null, data, collection); }); } @@ -125,20 +125,20 @@ module.exports = function (config, db, shareModel) { return updateData(collection, data, callback); }); } else { - updating = true; + updating = true; var stopUpdating = function (err, result, col) { config.debug && config.debug('Stop updating'); updating = false; if (err) { - return callback(err); + return callback && callback(err); } - return callback(null, result, col); + return callback && callback(null, result, col); }; - return collection.findOne({ _id: data._id}, function foundOne(err, result) { + return collection.findOne({_id: data._id}, function foundOne(err, result) { if (err) { config.error && config.error('ERR updateData', err); - return callback(err); + return callback && callback(err); } _.extend(result, data); return saveData(collection, result, stopUpdating); @@ -148,7 +148,7 @@ module.exports = function (config, db, shareModel) { /* - options: + * options: * collection (mandatory) * query (mandatory) * update (optional) : extends existing content @@ -158,7 +158,7 @@ module.exports = function (config, db, shareModel) { return db.collection(options.collection, function handleCollection(err, collection) { if (err) { config.error && config.error('ERR2 setMongoContent', err); - return callback(err); + return callback && callback(err); } if (options.operation) { data.version = options.operation.v; @@ -172,7 +172,7 @@ module.exports = function (config, db, shareModel) { collection.findOne(options.query, function foundOne(err, result) { if (err) { config.error && config.error('ERR3 setMongoContent', err); - return callback(err); + return callback && callback(err); } if (result) { data._id = result._id; @@ -191,16 +191,17 @@ module.exports = function (config, db, shareModel) { config.warn && config.warn('WARN setMongoAttribute updateShareDocumentPath shareModel.getSnapshot', documentId, err); return callback && callback(); } - var sub_data = data; + var sub_data = data; var sub_snapshot_data = doc.snapshot; - var equal_path = []; - var found = false; + var equal_path = []; + var found = false; var x; for (x = 0; !found && x < path.length; x += 1) { var key = path[x]; - if (sub_data && sub_data.hasOwnProperty(key) - && sub_snapshot_data && sub_snapshot_data.hasOwnProperty(key)) { - sub_data = sub_data[key]; + if (sub_data && sub_data.hasOwnProperty(key) && + sub_snapshot_data && + sub_snapshot_data.hasOwnProperty(key)) { + sub_data = sub_data[key]; sub_snapshot_data = sub_snapshot_data[key]; equal_path.push(key); } else if (!sub_snapshot_data || !sub_snapshot_data.hasOwnProperty(key)) { @@ -219,7 +220,10 @@ module.exports = function (config, db, shareModel) { if (sub_snapshot_data) { op.od = sub_snapshot_data; } - return shareModel.applyOp(documentId, { op: [op], v: doc.v }, function (err, result) { + return shareModel.applyOp(documentId, { + op: [op], + v: doc.v + }, function (err, result) { if (err) { config.error && config.error('ERR updateShareDocumentPath shareModel.applyOp', documentId, err); return callback && callback(); @@ -244,10 +248,12 @@ module.exports = function (config, db, shareModel) { } if (doc.type.name === 'text') { ops.push({ - d: doc.snapshot, p: 0 + d: doc.snapshot, + p: 0 }); ops.push({ - i: data, p: 0 + i: data, + p: 0 }); } else if (doc.type.name === 'json') { _.forEach(keys, function (key) { @@ -265,7 +271,10 @@ module.exports = function (config, db, shareModel) { } }); } - return shareModel.applyOp(documentId, { op: ops, v: doc.v }, function (err, result) { + return shareModel.applyOp(documentId, { + op: ops, + v: doc.v + }, function (err, result) { if (err) { config.warn && config.warn('WARN updateShareDocument shareModel.applyOp', documentId, err); return callback && callback(); @@ -297,16 +306,16 @@ module.exports = function (config, db, shareModel) { config.debug && config.debug('Stop ensuring', options); ensuring = false; if (err) { - return callback(err); + return callback && callback(err); } - return callback(null, result, col); + return callback && callback(null, result, col); }; getMongoContent(options, function document(err, result, col) { if (err) { if (/Data not found*/.test(err.message)) { var documentId = 'json:' + options.collection + ':' + options.name; - var data = {name: options.name}; + var data = {name: options.name}; setMongoContent(data, options, function (err, content_result, col) { var keys = _.keys(data); // reset all attributes; return updateShareDocument(documentId, data, keys, function updatedShareDocument() { @@ -332,21 +341,21 @@ module.exports = function (config, db, shareModel) { ensureContent(options, function document(err, result, col) { if (err) { config.error && config.error('ERR1 setMongoAttribute', err); - return callback(err); + return callback && callback(err); } var attribute_options = { collection: options.collection, - name: result.name + '.' + options.attribute + name: result.name + '.' + options.attribute }; - if (result.hasOwnProperty(options.attribute) - && result[options.attribute].guid) { + if (result.hasOwnProperty(options.attribute) && + result[options.attribute].guid) { attribute_options.query = { _id: result[options.attribute].guid }; } else { attribute_options.query = { parent: result._id, - name: result.name + '.' + options.attribute + name: result.name + '.' + options.attribute }; } @@ -355,7 +364,7 @@ module.exports = function (config, db, shareModel) { return ensureContent(attribute_options, function attribute(err, attribute_result) { if (err) { config.error && config.error('ERR2 setMongoAttribute ensureContent', err); - return callback(err); + return callback && callback(err); } var updateContent = true; if (result[options.attribute]) { @@ -365,11 +374,11 @@ module.exports = function (config, db, shareModel) { result[options.attribute].guid = attribute_result._id; } } else { - result[options.attribute] = { guid: attribute_result._id }; + result[options.attribute] = {guid: attribute_result._id}; } - attribute_result.parent = result._id; - attribute_result.name = result.name + '.' + options.attribute; + attribute_result.parent = result._id; + attribute_result.name = result.name + '.' + options.attribute; attribute_result[options.attribute] = data; if (options.operation) { attribute_result.version = options.operation.v; @@ -377,18 +386,18 @@ module.exports = function (config, db, shareModel) { return saveData(col, attribute_result, function saved(err) { if (err) { config.error && config.error('ERR3 setMongoAttribute', err); - return callback(err); + return callback && callback(err); } - var documentId = 'json:' + options.collection + ':' + result.name; - var type = options.type || 'text'; + var documentId = 'json:' + options.collection + ':' + result.name; + var type = options.type || 'text'; var attributeDocumentId = type + ':' + options.collection + ':' + result.name + ':' + options.attribute; - var keys = null; - var share_data = null; + var keys = null; + var share_data = null; if (type === 'json') { keys = _.keys(attribute_result); // reset all attributes; share_data = attribute_result; } else { - keys = [attribute_result.name]; + keys = [attribute_result.name]; share_data = data; } if (options.no_share) { @@ -399,15 +408,15 @@ module.exports = function (config, db, shareModel) { updateData(col, result, function saved(err) { if (err) { config.error && config.error('ERR3 setMongoAttribute', err); - return callback(err); + return callback && callback(err); } var path = [options.attribute, 'guid']; // reset just guid attribute; return updateShareDocumentPath(documentId, result, path, function updatedShareContent() { - return callback(null, attribute_result, col); + return callback && callback(null, attribute_result, col); }); }); } else { - callback(null, attribute_result, col); + return callback && callback(null, attribute_result, col); } }); }); @@ -416,11 +425,11 @@ module.exports = function (config, db, shareModel) { } return { - getMongoAttribute: getMongoAttribute, - getMongoContent: getMongoContent, - setMongoAttribute: setMongoAttribute, - setMongoContent: setMongoContent, - ensureContent: ensureContent, + getMongoAttribute: getMongoAttribute, + getMongoContent: getMongoContent, + setMongoAttribute: setMongoAttribute, + setMongoContent: setMongoContent, + ensureContent: ensureContent, updateShareDocument: updateShareDocument }; }; diff --git a/lib/preview.js b/lib/preview.js index 82dd841..fef68bd 100644 --- a/lib/preview.js +++ b/lib/preview.js @@ -1,26 +1,26 @@ +'use strict'; var Handlebars = require('handlebars'); -var markdown = require('markdown').markdown; -var _ = require('underscore'); -var less = require('less'); -var when = require('when'); +var markdown = require('markdown').markdown; +var _ = require('underscore'); +var less = require('less'); +var when = require('when'); module.exports = function (config, mongoDataInstance, helpers, markers) { - "use strict"; var getPreviewHTML; - var script_tag = markers.script_tag; + var script_tag = markers.script_tag; var script_regexp = markers.script_regexp; - var style_tag = markers.style_tag; + var style_tag = markers.style_tag; var style_regexp = markers.style_regexp; - var less_tag = markers.less_tag; + var less_tag = markers.less_tag; var less_regexp = markers.less_regexp; - var template_tag = markers.template_tag; + var template_tag = markers.template_tag; var template_regexp = markers.template_regexp; - var markdown_tag = markers.markdown_tag; + var markdown_tag = markers.markdown_tag; var markdown_regexp = markers.markdown_regexp; var remove_tag = markers.remove_tag; @@ -33,76 +33,76 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { // Script tag handling promises.push( helpers.replace(html, script_tag, function handleScriptMarker(result, callback) { - var parts = script_regexp.exec(result); + var parts = script_regexp.exec(result); var context = { collection: parts[1], - name: parts[2], - attribute: parts[3] + name: parts[2], + attribute: parts[3] }; - return callback(null, { - regExp: new RegExp(result, 'gmi'), - value: '' - }); + return callback && callback(null, { + regExp: new RegExp(result, 'gmi'), + value: '' + }); })); // Style tag handling promises.push( helpers.replace(html, style_tag, function handleStyleMarker(result, callback) { - var parts = style_regexp.exec(result); + var parts = style_regexp.exec(result); var context = { collection: parts[1], - name: parts[2], - attribute: parts[3] + name: parts[2], + attribute: parts[3] }; - return callback(null, { - regExp: new RegExp(result, 'gmi'), - value: '' - }); + return callback && callback(null, { + regExp: new RegExp(result, 'gmi'), + value: '' + }); })); // Less tag handling promises.push( helpers.replace(html, less_tag, function handleStyleMarker(result, callback) { - var parts = less_regexp.exec(result); + var parts = less_regexp.exec(result); var context = { collection: parts[1], - name: parts[2], - attribute: parts[3] + name: parts[2], + attribute: parts[3] }; - return callback(null, { - regExp: new RegExp(result, 'gmi'), - value: '' - }); + return callback && callback(null, { + regExp: new RegExp(result, 'gmi'), + value: '' + }); })); // Template tag handling promises.push( helpers.replace(html, template_tag, function handleTemplateMarker(result, callback) { - var parts = template_regexp.exec(result); + var parts = template_regexp.exec(result); var template = { collection: parts[1], - name: parts[2], - attribute: parts[3], - query: { name: parts[2]} + name: parts[2], + attribute: parts[3], + query: {name: parts[2]} }; - var context = { + var context = { collection: parts[4], - name: parts[5], - query: { name: parts[5]}, - req: options.req + name: parts[5], + query: {name: parts[5]}, + req: options.req }; return mongoDataInstance.getMongoContent(context, function handleContext(err, context_result) { if (err) { config.error && config.error('ERR template_tag getMongoContent', context); - return callback(err); + return callback && callback(err); } return mongoDataInstance.getMongoAttribute(template, function handleTemplate(err, template_result) { if (err) { config.error && config.error('ERR template_tag getMongoAttribute', template, err); - return callback(err); + return callback && callback(err); } var compiled_template = null; - var keys_to_collect = {}; + var keys_to_collect = {}; function collectKey(key) { return function () { @@ -110,7 +110,7 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { return keys_to_collect[key]; } keys_to_collect[key] = null; - return "waiting for content"; + return 'waiting for content'; }; } @@ -128,7 +128,7 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { compiled_template = handlebars.compile(template_result[template.attribute]); } catch (error1) { config.error && config.error('ERR template_tag Handlebars.compile', template, error1); - return callback(error1); + return callback && callback(error1); } var extendHandlebars_context = function (result) { var handlebars = {}; @@ -141,41 +141,43 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { }); return handlebars; }; - var handlebars_context = extendHandlebars_context(context_result); + var handlebars_context = extendHandlebars_context(context_result); try { compiled_template(handlebars_context); } catch (error2) { config.error && config.error('ERR template_tag Handlebars.render', template, context, error2); - return callback(error2); + return callback && callback(error2); } var promises = []; _.forEach(_.keys(keys_to_collect), function gatherKeyValues(key) { - var deferred = when.defer(); - var promise = deferred.promise; + //noinspection JSUnresolvedFunction + var deferred = when.defer(); + var promise = deferred.promise; promises.push(promise); var attribute_context = { collection: context.collection, - attribute: key, - query: { _id: context_result._id} + attribute: key, + query: {_id: context_result._id} }; return mongoDataInstance.getMongoAttribute(attribute_context, function cacheTemplateKey(err, template_key_result) { if (err) { config.error && config.error('ERR handlebar.registerHelper getMongoAttribute', err); deferred.reject(err); } - var value = template_key_result[key]; + var value = template_key_result[key]; keys_to_collect[key] = value; deferred.resolve(value); }); }); + //noinspection JSUnresolvedFunction return when.all(promises).then( function onSuccess() { - var rendered = null; + var rendered = null; try { rendered = compiled_template(handlebars_context); } catch (err) { config.error && config.error('ERR template_tag Handlebars.render', template, context, err); - return callback(err); + return callback && callback(err); } config.debug && config.debug('// handle markers on rendered template'); context.query = {_id: context_result._id}; @@ -186,13 +188,13 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { } return callback(null, { regExp: new RegExp(result, 'gmi'), - value: preview_html + value: preview_html }); }); }, function onFailure(err) { config.error && config.error('ERR template_tag resolving promises', err); - return callback(err); + return callback && callback(err); } ); }); @@ -202,32 +204,32 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { // Markdown tag handling promises.push( helpers.replace(html, markdown_tag, function handleMarkDownMarker(result, callback) { - var parts = markdown_regexp.exec(result); + var parts = markdown_regexp.exec(result); var attribute = { collection: parts[1], - name: parts[2], - attribute: parts[3], - query: { name: parts[2] } + name: parts[2], + attribute: parts[3], + query: {name: parts[2]} }; return mongoDataInstance.getMongoAttribute(attribute, function handleMarkdownContent(err, markdown_result) { if (err) { - return callback(err); + return callback && callback(err); } var html = markdown.toHTML(markdown_result[attribute.attribute]); - return callback(null, { - regExp: new RegExp(result, 'gmi'), - value: html - }); + return callback && callback(null, { + regExp: new RegExp(result, 'gmi'), + value: html + }); }); })); // Remove tag handling promises.push( helpers.replace(html, remove_tag, function handleRemoveMarker(result, callback) { - return callback(null, { - regExp: null, - value: "" - }); + return callback && callback(null, { + regExp: null, + value: '' + }); }, true)); return promises; @@ -241,7 +243,7 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { return text.replace(result.regExp, result.replacement); } - helpers.handTextManipulation(content, + return helpers.handTextManipulation(content, promises, handler, callback @@ -249,7 +251,7 @@ module.exports = function (config, mongoDataInstance, helpers, markers) { }; return { - getPreviewHTML: getPreviewHTML, + getPreviewHTML: getPreviewHTML, _replaceMarkers: replaceMarkers }; }; diff --git a/lib/responder.js b/lib/responder.js index 7a2bc9e..687a78f 100644 --- a/lib/responder.js +++ b/lib/responder.js @@ -1,10 +1,9 @@ - +'use strict'; /* * options.ext: determines content-type * options.attribute: sends result[options.attribute] in stead of result */ module.exports = function (config, options, res, next) { - "use strict"; return function responder(err, result) { if (err) { config.error && config.error('ERR responder', options, err); diff --git a/lib/routes.js b/lib/routes.js index 58695c3..a933fe3 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -1,20 +1,20 @@ +'use strict'; var responder = require('./responder.js'); var path = require('path'); -var fs = require('fs'); +var fs = require('fs'); module.exports = function (app, handlers, markers, config) { - "use strict"; var route; route = config.api.data + '/:collection/:guid/:attribute.:ext(css|less|js|html)'; app.get(route, function getAttributeByGUID(req, res, next) { - config.debug && config.debug('/data/:collection/:guid/:attribute.:ext(less|js|html)'); + config.debug && config.debug(config.api.data + '/:collection/:guid/:attribute.:ext(less|js|html)'); var options = { collection: req.params.collection, - attribute: req.params.attribute, - ext: req.params.ext, - query: {_id: req.params.guid} + attribute: req.params.attribute, + ext: req.params.ext, + query: {_id: req.params.guid} }; handlers.getAttribute(options, responder(config, options, res, next) @@ -25,11 +25,11 @@ module.exports = function (app, handlers, markers, config) { route = config.api.data + '/:collection/:guid.:ext(json)'; app.get(route, function getContentByGUID(req, res, next) { - config.debug && config.debug('/data/:collection/:guid.:ext(json)'); + config.debug && config.debug(config.api.data + '/:collection/:guid.:ext(json)'); var options = { collection: req.params.collection, - ext: req.params.ext, - query: {_id: req.params.guid} + ext: req.params.ext, + query: {_id: req.params.guid} }; handlers.getContent(options, responder(config, options, res, next) @@ -40,12 +40,12 @@ module.exports = function (app, handlers, markers, config) { route = config.api.content + '/:collection/:name/:attribute.:ext(css|less|js|html)'; app.get(route, function getAttributeByName(req, res, next) { - config.debug && config.debug('/content/:collection/:name/:attribute.:ext(less|js|html)'); + config.debug && config.debug(config.api.content + '/:collection/:name/:attribute.:ext(less|js|html)'); var options = { collection: req.params.collection, - attribute: req.params.attribute, - ext: req.params.ext, - query: {name: req.params.name} + attribute: req.params.attribute, + ext: req.params.ext, + query: {name: req.params.name} }; handlers.getAttribute(options, responder(config, options, res, next) @@ -53,14 +53,14 @@ module.exports = function (app, handlers, markers, config) { } ); - route = config.api.content + '/content/:collection/:name.:ext(json)'; + route = config.api.content + '/:collection/:name.:ext(json)'; app.get(route, function getContentByName(req, res, next) { - config.debug && config.debug('/content/:collection/:name.:ext(json)'); + config.debug && config.debug(config.api.content + '/:collection/:name.:ext(json)'); var options = { collection: req.params.collection, - ext: req.params.ext, - query: {name: req.params.name} + ext: req.params.ext, + query: {name: req.params.name} }; handlers.getContent(options, responder(config, options, res, next) @@ -72,19 +72,20 @@ module.exports = function (app, handlers, markers, config) { route = config.api.preview + '/:collection/:name.:ext(html|md)'; app.get(route, function getPreviewContent(req, res, next) { - config.debug && config.debug('/page/:collection/:name.:ext(html|md)'); + config.debug && config.debug(config.api.preview + '/:collection/:name.:ext(html|md)'); var options = { collection: req.params.collection, - ext: req.params.ext, - query: {name: req.params.name}, - req: { query: req.query || {}, + ext: req.params.ext, + query: {name: req.params.name}, + req: { + query: req.query || {}, headers: req.headers } }; if (options.ext === 'md') { - var attribute_parts = options.query.name.split('.'); + var attribute_parts = options.query.name.split('.'); var markdownDocument = markers.createTag('markdown', options.collection, attribute_parts[0], attribute_parts[1]); - return handlers.getPreviewHTML(markdownDocument, { req: options.req }, + return handlers.getPreviewHTML(markdownDocument, {req: options.req}, responder(config, options, res, next) ); } @@ -94,20 +95,21 @@ module.exports = function (app, handlers, markers, config) { } if (result) { var attribute_parts = options.query.name.split('.'); - var attribute = attribute_parts[attribute_parts.length - 1]; + var attribute = attribute_parts[attribute_parts.length - 1]; var attribute_value = result[attribute]; if (attribute_value) { - options.name = attribute_parts[0]; + options.name = attribute_parts[0]; var preview_options = { collection: options.collection, - name: options.name, - attribute: attribute, - query: {_id: result._id}, - req: options.req + name: options.name, + attribute: attribute, + query: {_id: result._id}, + req: options.req }; config.debug && config.debug('getPreviewContent content', attribute_value); - handlers.getPreviewHTML(attribute_value, preview_options, + handlers.getPreviewHTML(attribute_value, + preview_options, responder(config, options, res, next) ); } else { @@ -124,7 +126,7 @@ module.exports = function (app, handlers, markers, config) { route = config.api.importer + '/:filename'; app.get(route, function importFile(req, res, next) { var filename = path.resolve(config.statics.importer_path, req.params.filename); - config.debug && config.debug('/importer/:filename', filename); + config.debug && config.debug(config.api.importer + '/:filename', filename); fs.readFile(filename, 'utf-8', function handleFileContent(err, sub_doc) { if (err) { config.error && config.error('ERR readFile', filename, err); diff --git a/lib/share.js b/lib/share.js index 32be6ae..9023fff 100644 --- a/lib/share.js +++ b/lib/share.js @@ -1,19 +1,19 @@ +'use strict'; var ShareJS = require('share'); module.exports = function (config, app, db) { - "use strict"; // share wraps express app with http.Server - if (config - && config.share - && config.share.db - && config.share.db.type === 'mongo') { + if (config && + config.share && + config.share.db && + config.share.db.type === 'mongo') { config.share.db.client = db; } var server = ShareJS.server.attach(app, config.share); - var model = app.model; + var model = app.model; return { server: server, - model: model + model: model }; }; diff --git a/lib/shareHandlers.js b/lib/shareHandlers.js index 422e29a..6de2c1a 100644 --- a/lib/shareHandlers.js +++ b/lib/shareHandlers.js @@ -1,5 +1,5 @@ +'use strict'; module.exports = function (config, model, mongoDataInstance) { - "use strict"; var timers = {}; function handleMongoGetResult(options) { @@ -13,18 +13,18 @@ module.exports = function (config, model, mongoDataInstance) { if (options.type === 'json') { result[options.attribute] = {}; } else { - result[options.attribute] = ""; + result[options.attribute] = ''; } } notFound = true; } else { - config.error && config.error('ERR1 handleMongoGetResult.handleResult Error retrieving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err); + config.error && config.error('ERR1 handleMongoGetResult.handleResult Error retrieving document ', options.collection, JSON.stringify(options.query), options.attribute || '', err); } } if (result || notFound) { var operation = null; config.debug && config.debug('handleMongoGetResult options', options, result); - var data = result; + var data = result; if (options.attribute) { data = result[options.attribute]; } @@ -33,13 +33,19 @@ module.exports = function (config, model, mongoDataInstance) { if (data instanceof String) { data = JSON.parse(data); } - operation = { op: [ - { p: [], oi: data, od: null } - ], v: version }; + operation = { + op: [ + {p: [], oi: data, od: null} + ], + v: version + }; } else if (options.type === 'text') { - operation = { op: [ - {i: data, p: 0} - ], v: version }; + operation = { + op: [ + {i: data, p: 0} + ], + v: version + }; } if (operation) { model.applyOp(options.documentId, operation, function appliedOp(error, version) { @@ -60,13 +66,13 @@ module.exports = function (config, model, mongoDataInstance) { var splitId = documentId.split(':'); var options = { documentId: documentId, - type: splitId[0], + type: splitId[0], collection: splitId[1], - attribute: null + attribute: null }; if (splitId.length === 4) { // options.query = {_id: splitId[2]}; - options.query = {name: splitId[2]}; + options.query = {name: splitId[2]}; options.attribute = splitId[3]; mongoDataInstance.getMongoAttribute(options, handleMongoGetResult(options)); } else { @@ -79,15 +85,18 @@ module.exports = function (config, model, mongoDataInstance) { function handleMongoSetResult(options, current, callback) { function handleResult(err, result) { if (err) { - config.error && config.error('ERR1 handleMongoSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err); + config.error && config.error('ERR1 handleMongoSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || '', err); return callback && callback(err); } config.debug && config.debug('current', current, 'result', result, 'options', options); if ((!current || !current.name) && (result.name || options.name)) { - var name = result.name || options.name; - var operation = { op: [ - { p: ['name'], oi: name, od: null } - ], v: options.operation.v }; + var name = result.name || options.name; + var operation = { + op: [ + {p: ['name'], oi: name, od: null} + ], + v: options.operation.v + }; model.applyOp(options.documentId, operation, function appliedOp(error, version) { config.debug && config.debug('setResult applyOp version', version); if (error) { @@ -97,7 +106,7 @@ module.exports = function (config, model, mongoDataInstance) { return callback && callback(null, version); }); } else { - return callback(null, null); + return callback && callback(null, null); } } @@ -107,11 +116,11 @@ module.exports = function (config, model, mongoDataInstance) { function handleMongoAttributeSetResult(options, current, callback) { function handleResult(err, result) { if (err) { - config.error && config.error('ERR1 handleMongoAttributeSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || "", err); - return callback(err); + config.error && config.error('ERR1 handleMongoAttributeSetResult Error while saving document ', options.collection, JSON.stringify(options.query), options.attribute || '', err); + return callback && callback(err); } config.debug && config.debug('current', current, 'result', result); - return callback(null, null); + return callback && callback(null, null); } return handleResult; @@ -160,31 +169,31 @@ module.exports = function (config, model, mongoDataInstance) { return; } - var splitId = documentId.split(':'); - var options = { + var splitId = documentId.split(':'); + var options = { documentId: documentId, - type: splitId[0], + type: splitId[0], collection: splitId[1], - name: splitId[2], - attribute: null, - operation: operation, - no_share: true // prevent circular updates. + name: splitId[2], + attribute: null, + operation: operation, + no_share: true // prevent circular updates. }; - var timer = { + var timer = { current: current, options: options }; var attribute = false; if (splitId.length === 4) { // options.query = {_id: splitId[2]}; - options.query = {name: splitId[2]}; + options.query = {name: splitId[2]}; options.attribute = splitId[3]; - attribute = true; + attribute = true; } else { options.query = {name: splitId[2]}; } if (timers[documentId]) { - timer.timer_id = timers[documentId].timer_id; + timer.timer_id = timers[documentId].timer_id; timers[documentId] = timer; config.debug && config.debug('resetting timer', documentId); } else { diff --git a/package.json b/package.json index 6ea0393..1bb58f2 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,45 @@ { - "name": "Prototyper", - "version": "0.0.1", - "main": "server.js", - "config" : { - "port" : "8000" + "name": "Prototyper", + "version": "0.0.1", + "main": "server.js", + "config": { + "port": "8000" }, - "engine": "node 0.10.4", - "private": "true", - "dependencies": { - "share": "~0.6.0", - "connect": "~2.7.9", - "express": "~3.2.4", - "bson": "~0.1.8", - "mongodb": "~1.2.14", + "engine": "node 0.10.38", + "private": "true", + "dependencies": { + "share": "~0.6.0", + "connect": "~2.7.9", + "express": "~3.2.4", + "bson": "~0.1.8", + "mongodb": "~1.2.14", "handlebars": "~1.0.10", "underscore": "~1.4.4", - "less": "~1.3.3", - "when": "~2.1.0", - "markdown": "~0.4.0", - "async": "~0.2.8" + "less": "~1.3.3", + "when": "~2.1.0", + "markdown": "~0.4.0", + "async": "~0.2.8" }, "devDependencies": { "sockjs": "~0.3.7", - "chai": "*", - "mocha": "*", - "sinon": "*", - "groc": "*" + "chai": "*", + "mocha": "*", + "sinon": "*", + "groc": "*" }, - "repository": "git://github.com/aikomastboom/Prototyper.git", - "author": "Aiko Mastboom", - "license": "Unknown", - "readmeFilename": "README.md", - "directories": { + "repository": "git://github.com/aikomastboom/Prototyper.git", + "author": "Aiko Mastboom", + "license": "Unknown", + "readmeFilename": "README.md", + "directories": { "test": "test" }, - "description": "README.md", - "scripts": { - "test": "./node_modules/.bin/mocha", + "description": "README.md", + "scripts": { + "test": "./node_modules/.bin/mocha", "install": "./bin/installit", - "deploy": "./bin/deployit", - "doc":"./bin/docit", - "cov": "./bin/coverit" + "deploy": "./bin/deployit", + "doc": "./bin/docit", + "cov": "./bin/coverit" } } diff --git a/server.js b/server.js index 5b96366..1886ff4 100644 --- a/server.js +++ b/server.js @@ -1,81 +1,101 @@ -"use strict"; -process.title = "Prototyper"; +'use strict'; +process.title = 'Prototyper'; -var connect = require('connect'); -var express = require('express'); -var MongoClient = require('mongodb').MongoClient; -var addRoutes = require('./lib/routes.js'); -var shareServer = require('./lib/share.js'); +var connect = require('connect'); +var express = require('express'); +var MongoClient = require('mongodb').MongoClient; +var addRoutes = require('./lib/routes.js'); +var shareServer = require('./lib/share.js'); var shareHandlers = require('./lib/shareHandlers.js'); -var mongoData = require('./lib/mongoData.js'); -var preview = require('./lib/preview.js'); -var importer = require('./lib/importer.js'); -var handlers = require('./lib/handlers.js'); -var markers = require('./lib/markers.js'); -var helpers = require('./lib/helpers.js'); +var mongoData = require('./lib/mongoData.js'); +var preview = require('./lib/preview.js'); +var importer = require('./lib/importer.js'); +var handlers = require('./lib/handlers.js'); +var markers = require('./lib/markers.js'); +var helpers = require('./lib/helpers.js'); var config = { - debug: function () { + debug: function () { if (process.env.DEBUG) { var error = arguments[0] && arguments[0].message || arguments[1] && arguments[1].message || arguments[2] && arguments[2].message; - var args = Array.prototype.slice.call(arguments); - var log = { level: 'debug', message: args, timestamp: Date.now(), error: error}; + var args = Array.prototype.slice.call(arguments); + var log = { + level: 'debug', + message: args, + timestamp: Date.now(), + error: error + }; console.log(JSON.stringify(log)); } }, - info: function () { - var error = arguments[0] && arguments[0].message || - arguments[1] && arguments[1].message || - arguments[2] && arguments[2].message; - var args = Array.prototype.slice.call(arguments); - var log = { level: 'info', message: args, timestamp: Date.now(), error: error}; - console.log(JSON.stringify(log)); - }, - warn: function () { - var error = arguments[0] && arguments[0].message || - arguments[1] && arguments[1].message || - arguments[2] && arguments[2].message; - var args = Array.prototype.slice.call(arguments); - var log = { level: 'warn', message: args, timestamp: Date.now(), error: error}; - console.warn(JSON.stringify(log)); - }, - error: function () { + info: function () { var error = arguments[0] && arguments[0].message || arguments[1] && arguments[1].message || arguments[2] && arguments[2].message; - var args = Array.prototype.slice.call(arguments); - var log = { level: 'error', message: args, timestamp: Date.now(), error: error}; + var args = Array.prototype.slice.call(arguments); + var log = { + level: 'info', + message: args, + timestamp: Date.now(), + error: error + }; + console.log(JSON.stringify(log)); + }, + warn: function () { + var error = arguments[0] && arguments[0].message || + arguments[1] && arguments[1].message || + arguments[2] && arguments[2].message; + var args = Array.prototype.slice.call(arguments); + var log = { + level: 'warn', + message: args, + timestamp: Date.now(), + error: error + }; + console.warn(JSON.stringify(log)); + }, + error: function () { + var error = arguments[0] && arguments[0].message || + arguments[1] && arguments[1].message || + arguments[2] && arguments[2].message; + var args = Array.prototype.slice.call(arguments); + var log = { + level: 'error', + message: args, + timestamp: Date.now(), + error: error + }; console.error(JSON.stringify(log)); }, - port: process.env.npm_package_config_port || 8000, - mongo: { - server: "mongodb://localhost:27017/Prototyper", - options: { - db: { + port: process.env.npm_package_config_port || 8000, + mongo: { + server: 'mongodb://localhost:27017/Prototyper', + options: { + db: { native_parser: true, - fsync: true + fsync: true }, server: { - maxPoolSize: 10, + maxPoolSize: 10, auto_reconnect: true } }, savedelay: 200 }, - share: { - sockjs: { - prefix: '', - response_limit: 128 * 1024, - websocket: true, - jsessionid: false, - heartbeat_delay: 25000, + share: { + sockjs: { + prefix: '', + response_limit: 128 * 1024, + websocket: true, + jsessionid: false, + heartbeat_delay: 25000, disconnect_delay: 5000, - log: function(severity, line) { + log: function (severity, line) { if (process.env.DEBUG) { if (severity === 'info') { - config.info && config.info(severity,line); + config.info && config.info(severity, line); } else if (severity === 'error') { config.error && config.error(severity, line); } else { @@ -83,29 +103,29 @@ var config = { } } }, - sockjs_url: 'https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js' + sockjs_url: 'https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js' }, staticpath: '/lib/share', - db: {type: 'none'} + db: {type: 'none'} // db: { // type: 'mongo', // opsCollectionPerDoc: false // } }, - api: { - content: '/content', - data: '/data', - preview: '/page', + api: { + content: '/content', + data: '/data', + preview: '/page', importer: '/importer' }, statics: { dev_favicon_path: __dirname + '/public/favicon_dev.ico', - importer_path: __dirname + '/public', - public_path: __dirname + '/public', - doc_path: __dirname + '/doc', - markdown_client: __dirname + '/node_modules/markdown/lib', - ace_client: __dirname + '/node_modules/share/examples/lib/ace', - async_client: __dirname + '/node_modules/async/lib' + importer_path: __dirname + '/public', + public_path: __dirname + '/public', + doc_path: __dirname + '/doc', + markdown_client: __dirname + '/node_modules/markdown/lib', + ace_client: __dirname + '/node_modules/share/examples/lib/ace', + async_client: __dirname + '/node_modules/async/lib' } }; @@ -119,10 +139,12 @@ express.static.mime.define({ if (process.env.DEBUG) { //app.use(connect.logger()); - var stream = { write: function(str) { - config.debug && config.debug(str); - }}; - app.use(connect.logger({ immediate: false, format: 'dev', stream: stream })); + var stream = { + write: function (str) { + config.debug && config.debug(str); + } + }; + app.use(connect.logger({immediate: false, format: 'dev', stream: stream})); } //noinspection JSUnresolvedFunction app.use(express.compress()); @@ -155,8 +177,8 @@ MongoClient.connect(config.mongo.server, config.mongo.options, function connecti } config.debug && config.debug('database connected'); - var share = shareServer(config, app, db); - var model = share.model; + var share = shareServer(config, app, db); + var model = share.model; var server = share.server; config.debug && config.debug('share attached'); @@ -187,13 +209,24 @@ MongoClient.connect(config.mongo.server, config.mongo.options, function connecti function exit(code) { db.close(); - process.exit(code); + // Probably there are also some other listeners for uncaughtException, + // so we postpone process.exit + process.nextTick(function () { + process.exit(code); + }); } + process.on('uncaughtException', function (err) { + config.error && config.error('HALTING ON UNCAUGHT EXCEPTION:' + err.message, err); + config.error && config.error(err.stack); + config.error && config.error('EXIT 1'); + return exit(1); + }); + server.on('error', function (err) { config.error && config.error('Server error', err); if (err.code && err.code === 'EADDRINUSE') { - exit(2); + return exit(2); } }); diff --git a/test/test.helpers.js b/test/test.helpers.js index cec80d9..90811ce 100644 --- a/test/test.helpers.js +++ b/test/test.helpers.js @@ -1,17 +1,18 @@ +'use strict'; +//noinspection JSUnresolvedVariable var libpath = process.env.PROTOTYPER_COV ? '../lib-cov' : '../lib'; -var helpers = require(libpath + '/helpers.js'); -var markers = require(libpath + '/markers.js'); -var chai = require('chai'); +var helpers = require(libpath + '/helpers.js'); +var markers = require(libpath + '/markers.js'); +var chai = require('chai'); chai.config.includeStack = true; // defaults to false chai.config.showDiff = false; // defaults to false var expect = chai.expect; -var when = require('when'); +var when = require('when'); describe('Helpers', function () { - "use strict"; - var config = { + var config = { debug: function () { //console.log(arguments); }, @@ -20,10 +21,10 @@ describe('Helpers', function () { } }; var markersInstance = markers(config); - var marker_prefix = ''; - var helper = helpers({ - prefix: marker_prefix, + var marker_prefix = ''; + var helper = helpers({ + prefix: marker_prefix, postfix: marker_postfix }); @@ -52,7 +53,7 @@ describe('Helpers', function () { }; } - var i, values = [ null, undefined, '', 'hello', {}, []]; + var i, values = [null, undefined, '', 'hello', {}, []]; for (i = 0; i < values.length; i += 1) { it('should ignore non text input ' + values[i], testText(values[i])); } @@ -62,7 +63,7 @@ describe('Helpers', function () { it('should call getReplacement fail on error', function (done) { var marker = ''; - var text = 'hello' + marker + 'world'; + var text = 'hello' + marker + 'world'; function getReplacement(result, callback) { expect(result).to.be.equal(marker); @@ -84,7 +85,7 @@ describe('Helpers', function () { it('should call getReplacement (once)', function (done) { var marker = ''; - var text = 'Hello' + marker + 'World' + marker + '!!'; + var text = 'Hello' + marker + 'World' + marker + '!!'; function getReplacement(result, callback) { expect(result).to.be.equal(marker); @@ -92,7 +93,7 @@ describe('Helpers', function () { callback(null, {}); } - var once = true; + var once = true; var promise = helper.replace(text, null, getReplacement, once); expect(when.isPromise(promise)).to.be.ok; promise.then( @@ -117,18 +118,19 @@ describe('Helpers', function () { it('should call getReplacement', function (done) { var marker = ''; - var text = 'Hello' + marker + 'World' + marker + '!!'; + var text = 'Hello' + marker + 'World' + marker + '!!'; function getReplacement(result, callback) { expect(result).to.be.equal(marker); expect(callback).to.be.a('function'); callback(null, { regExp: new RegExp('What?'), - value: '#'}); + value: '#' + }); } - var once = false; + var once = false; var promise = helper.replace(text, null, getReplacement, once); expect(when.isPromise(promise)).to.be.ok; promise.then( @@ -161,10 +163,10 @@ describe('Helpers', function () { it('should handle variable tags', function (done) { var marker_tag = 'test__([A-Za-z0-9]+)'; - var marker1 = ''; - var marker2 = ''; - var text = 'Hello' + marker1 + 'World' + marker2 + '!!'; - var called = 0; + var marker1 = ''; + var marker2 = ''; + var text = 'Hello' + marker1 + 'World' + marker2 + '!!'; + var called = 0; function getReplacement(result, callback) { if (called) { @@ -176,11 +178,12 @@ describe('Helpers', function () { expect(callback).to.be.a('function'); callback(null, { regExp: new RegExp('What?'), - value: '#'}); + value: '#' + }); } - var once = false; + var once = false; var promise = helper.replace(text, marker_tag, getReplacement, once); expect(when.isPromise(promise)).to.be.ok; promise.then( @@ -209,12 +212,12 @@ describe('Helpers', function () { it('should handle tags in tags', function (done) { var marker_tag = 'test_([A-Za-z0-9]+)__([\\w\\W]*?)__\\1_test'; - var marker1 = ''; - var marker2 = ''; - var marker3 = ''; - var text = 'Hello' + marker1 + 'World' + marker2 + '!!' + marker3 + + var marker1 = ''; + var marker2 = ''; + var marker3 = ''; + var text = 'Hello' + marker1 + 'World' + marker2 + '!!' + marker3 + 'Greetings' + marker1 + 'Earthlings' + marker3 + '!!' + marker2; - var called = 0; + var called = 0; function getReplacement(result, callback) { //console.log('result',called,result); @@ -229,11 +232,12 @@ describe('Helpers', function () { expect(callback).to.be.a('function'); callback(null, { regExp: new RegExp('What?'), - value: '#'}); + value: '#' + }); } - var once = false; + var once = false; var promise = helper.replace(text, marker_tag, getReplacement, once); expect(when.isPromise(promise)).to.be.ok; promise.then( @@ -278,7 +282,7 @@ describe('Helpers', function () { }; } - var i, values = [ null, undefined, '', 'hello', {}, []]; + var i, values = [null, undefined, '', 'hello', {}, []]; for (i = 0; i < values.length; i += 1) { it('should return input when there are no promisses ' + values[i], testText(values[i])); } diff --git a/test/test.mongoData.js b/test/test.mongoData.js index c286505..27469e3 100644 --- a/test/test.mongoData.js +++ b/test/test.mongoData.js @@ -1,12 +1,13 @@ -"use strict"; -var libPath = process.env.PROTOTYPER_COV ? '../lib-cov' : '../lib'; -var chai = require('chai'); +'use strict'; +//noinspection JSUnresolvedVariable +var libPath = process.env.PROTOTYPER_COV ? '../lib-cov' : '../lib'; +var chai = require('chai'); chai.config.includeStack = true; // defaults to false chai.config.showDiff = false; // defaults to false var expect = chai.expect; var mongoData = require(libPath + '/mongoData.js'); -var config = { +var config = { debug: function () { //console.log(arguments); }, @@ -35,34 +36,41 @@ describe('mongoData', function () { throw new Error('fail:' + JSON.stringify(arguments)); } - var col = {findOne: findOne}; - var db = { collection: function (c, cb) { - //console.log('collection arguments', arguments); - if (c === 'test_error') { - return cb(new Error(c)); + var col = {findOne: findOne}; + var db = { + collection: function (c, cb) { + //console.log('collection arguments', arguments); + if (c === 'test_error') { + return cb(new Error(c)); + } + return cb(null, col); } - return cb(null, col); - }}; - var shareModel = {}; - var option_list = [ + }; + var shareModel = {}; + var option_list = [ {}, // no collection {query: 'q'}, // no collection {collection: 'test_error'}, // bad collection {collection: 'col'}, // no query - {collection: 'no_hex', - query: {_id: 'id'} // not a hexString + { + collection: 'no_hex', + query: {_id: 'id'} // not a hexString }, - {collection: 'no_col', // trigger findOne error - query: {_id: '123456789012345678901234'} + { + collection: 'no_col', // trigger findOne error + query: {_id: '123456789012345678901234'} }, - {collection: 'col', // trigger null result - query: {_id: '234567890123456789012345'} + { + collection: 'col', // trigger null result + query: {_id: '234567890123456789012345'} }, - {collection: 'col', // trigger '' result - query: {_id: '345678901234567890123456'} + { + collection: 'col', // trigger '' result + query: {_id: '345678901234567890123456'} }, - {collection: 'ok', // trigger 'ok' result - query: {_id: '456789012345678901234567'} + { + collection: 'ok', // trigger 'ok' result + query: {_id: '456789012345678901234567'} } ]; var mongoDataInstance = mongoData(config, db, shareModel); @@ -91,7 +99,9 @@ describe('mongoData', function () { } for (i = 0; i < option_list.length; i += 1) { - it('should handle arguments correctly', testArguments(option_list[i])); + it('should handle arguments correctly ' + JSON.stringify(option_list[i]), + testArguments(option_list[i]) + ); } }); });