Simplify the settings generator
authorJack Allnutt <jack@allnutt.eu>
Fri, 22 Aug 2014 09:41:14 +0000 (10:41 +0100)
committerJack Allnutt <jack@allnutt.eu>
Fri, 22 Aug 2014 09:41:14 +0000 (10:41 +0100)
settingsgenerator.js:
* getSettings' callback now passes an error object as its first argument
* generateSettings now returns a Promise

httphandler.js:
* serveSettings will now respond with HTTP 500 (Internal Server Error) if
    there is an error generating the settings object

server/httphandler.js
server/settingsgenerator.js

index c3fc067fa104efb60740d72a250c89aff44b41a4..1d4e5f79386024a66ebcf7950c11071a722f3cea 100644 (file)
@@ -2,8 +2,6 @@ var url         = require('url'),
     fs          = require('fs'),
     node_static = require('node-static'),
     Negotiator  = require('negotiator'),
-    _           = require('lodash'),
-    config      = require('./configuration.js'),
     winston     = require('winston'),
     SettingsGenerator = require('./settingsgenerator.js'),
     Stats       = require('./stats.js');
@@ -92,7 +90,7 @@ fs.readdir('client/assets/locales', function (err, files) {
  * Find the closest translation we have for the language
  * set in the browser.
  **/
-var serveMagicLocale = function (request, response) {
+function serveMagicLocale(request, response) {
     var default_locale_id = 'en-gb',
         found_locale, negotiator;
 
@@ -113,27 +111,32 @@ var serveMagicLocale = function (request, response) {
         Vary: 'Accept-Language',
         'Content-Language': found_locale
     }, request, response);
-};
+}
 
 
 
 /**
  * Handle the settings.json request
  */
-var serveSettings = function(request, response) {
+function serveSettings(request, response) {
     var referrer_url,
-        debug = false,
-        settings;
+        debug = false;
 
     // Check the referrer for a debug option
-    if (request.headers['referer']) {
-        referrer_url = url.parse(request.headers['referer'], true);
+    if (request.headers.referer) {
+        referrer_url = url.parse(request.headers.referer, true);
         if (referrer_url.query && referrer_url.query.debug) {
             debug = true;
         }
     }
 
-    SettingsGenerator.get(debug, function(settings) {
+    SettingsGenerator.get(debug, function(err, settings) {
+        if (err) {
+            winston.error('Error generating settings', err);
+            response.writeHead(500, 'Internal Server Error');
+            return response.end();
+        }
+
         if (request.headers['if-none-match'] && request.headers['if-none-match'] === settings.hash) {
             response.writeHead(304, 'Not Modified');
             return response.end();
@@ -145,4 +148,4 @@ var serveSettings = function(request, response) {
         });
         response.end(settings.settings);
     });
-};
+}
index 0eefe79d7cb91851b330d59943024cf2709b327b..176e86d8b04dcf2ec7b9d2b9158f4599ddcc35d8 100644 (file)
@@ -1,5 +1,6 @@
 var fs          = require('fs'),
     crypto      = require('crypto'),
+    Promise     = require('es6-promise').Promise,
     config      = require('./configuration.js');
 
 
@@ -31,15 +32,16 @@ config.on('loaded', function () {
 function getSettings(debug, callback) {
     var settings = cached_settings[debug ? 'debug' : 'production'];
 
-    var returnSettings = function() {
-        callback(settings);
-    };
-
     // Generate the settings if we don't have them cached as yet
     if (settings.settings === '') {
-        generateSettings(debug, returnSettings);
+        generateSettings(debug).then(function (settings) {
+            cached_settings[debug ? 'debug' : 'production'] = settings;
+            callback(null, settings);
+        }, function (err) {
+            callback(err);
+        });
     } else {
-        returnSettings();
+        callback(null, settings);
     }
 }
 
@@ -48,7 +50,7 @@ function getSettings(debug, callback) {
  * Generate a settings object for the client.
  * Settings include available translations, default client config, etc
  */
-function generateSettings(debug, callback) {
+function generateSettings(debug) {
     var vars = {
             server_settings: {},
             client_plugins: [],
@@ -92,92 +94,73 @@ function generateSettings(debug, callback) {
 
     addScripts(vars, debug);
 
-    // Further jobs depend on callbacks, so tally up completed jobs before callback()
-    var total_jobs = 2,
-        completed_jobs = 0,
-        jobComplete = function() {
-            completed_jobs++;
-
-            if (completed_jobs < total_jobs)
-                return;
-
-            settings = cached_settings[debug?'debug':'production'];
-            settings.settings = JSON.stringify(vars);
-            settings.hash = crypto.createHash('md5').update(settings.settings).digest('hex');
-
-            callback();
-        };
-
-    addThemes(vars, jobComplete);
-    addTranslations(vars, jobComplete);
-
-}
-
-
-function addThemes(vars, callback) {
-    readThemeInfo(config.get().client_themes || ['relaxed'], function (err, themes) {
-        if (err) {
-            return callback(err);
-        }
-
+    return Promise.all([addThemes().then(function (themes) {
         vars.themes = themes;
-        return callback();
+    }), addTranslations().then(function (translations) {
+        vars.translations = translations;
+    })]).then(function () {
+        var settings = JSON.stringify(vars);
+        return ({
+            settings: settings,
+            hash: crypto.createHash('md5').update(settings).digest('hex')
+        });
     });
 }
 
 
-function readThemeInfo(themes, prev, callback) {
-    "use strict";
-    var theme = themes[0];
-
-    if (typeof prev === 'function') {
-        callback = prev;
-        prev = [];
-    }
-
-    fs.readFile(__dirname + '/../client/assets/themes/' + theme.toLowerCase() + '/theme.json', function (err, theme_json) {
-        if (err) {
-            return callback(err);
-        }
-
-        try {
-            theme_json = JSON.parse(theme_json);
-        } catch (e) {
-            return callback(e);
-        }
-
-        prev.push(theme_json);
-
-        if (themes.length > 1) {
-            return readThemeInfo(themes.slice(1), prev, callback);
-        }
-
-        callback(null, prev);
-    });
+function addThemes() {
+    return (config.get().client_themes || ['relaxed']).reduce(function (prom, theme) {
+        return prom.then(function (themes) {
+            return new Promise(function readThemeInfo(resolve, reject) {
+                fs.readFile(__dirname + '/../client/assets/themes/' + theme.toLowerCase() + '/theme.json', function (err, theme_json) {
+                    var theme;
+                    if (err) {
+                        return reject(err);
+                    }
+
+                    try {
+                        theme = JSON.parse(theme_json);
+                    } catch (e) {
+                        return reject(e);
+                    }
+
+                    themes.push(theme);
+                    resolve(themes);
+                });
+            });
+        });
+    }, Promise.resolve([]));
 }
 
-
-function addTranslations(vars, callback) {
-    // Get a list of available translations
-    fs.readFile(__dirname + '/../client/src/translations/translations.json', function (err, translations) {
-        if (err) {
-            return callback(err);
-        }
-
-        translations = JSON.parse(translations);
-        fs.readdir(__dirname + '/../client/src/translations/', function (err, pofiles) {
+function addTranslations() {
+    return new Promise(function (resolve, reject) {
+        fs.readFile(__dirname + '/../client/src/translations/translations.json', function readTranslations(err, translations) {
             if (err) {
-                return callback(err);
+                return reject(err);
+            }
+
+            try {
+                translations = JSON.parse(translations);
+            } catch (e) {
+                return reject(e);
             }
+            
+            fs.readdir(__dirname + '/../client/src/translations/', function readTranslationFile(err, pofiles) {
+                var trans = [];
 
-            pofiles.forEach(function (file) {
-                var locale = file.slice(0, -3);
-                if ((file.slice(-3) === '.po') && (locale !== 'template')) {
-                    vars.translations.push({tag: locale, language: translations[locale]});
+                if (err) {
+                    return reject(err);
                 }
-            });
 
-            return callback();
+                pofiles.forEach(function (file) {
+                    var locale = file.slice(0, -3);
+                    if ((file.slice(-3) === '.po') && (locale !== 'template')) {
+                        trans.push({tag: locale, language: translations[locale]});
+                    }
+                });
+
+                resolve(trans);
+            });
         });
     });
 }
@@ -265,4 +248,4 @@ function addScripts(vars, debug) {
             'src/applets/startup.js'
         ]
     ]);
-}
\ No newline at end of file
+}