Browse Source

produceConfigObject finds and merges .amd.json files

Herbert Vojčík 10 years ago
parent
commit
03ff22ee1b

+ 65 - 0
lib/config-builder.js

@@ -0,0 +1,65 @@
+var path = require('path'),
+    _ = require('lodash'),
+    findit = require('findit'),
+    fs = require('fs');
+
+function eachConfigFile(root, callback) {
+    var result = {files: [], dirs: []};
+    var find = findit(root, {followSymlinks: true});
+    find.on('file', function (file, stat) {
+        if (file.match(/\.amd\.json$/)) {
+            result.files[file] = stat;
+        }
+    });
+    find.on('directory', function (dir, stat, stop) {
+        result.dirs[dir] = stat;
+    });
+    find.on('end', function () {
+        callback(null, result);
+    });
+}
+
+exports.produceConfigObject = function (root, callback) {
+    eachConfigFile(root, function (err, filesAndDirs) {
+        if (err) {
+            callback(err);
+            return;
+        }
+
+        var dirExists = {};
+        var dirs = Object.keys(filesAndDirs.dirs);
+        for (var i = 0; i < dirs.length; i++) {
+            dirExists[path.basename(dirs[i])] = true;
+        }
+
+        var result;
+        var files = Object.keys(filesAndDirs.files);
+        var firstPass = [], secondPass = [];
+        for (var i = 0; i < files.length; i++) {
+            var file = files[i];
+            var basename = path.basename(file);
+            var specifier = basename.replace(/\.amd\.json$/, "");
+            if (specifier == "" || specifier[0] == ".") {
+                continue;
+            } else if (specifier == "local") {
+                firstPass.push(file);
+            } else if (dirExists[specifier]) {
+                secondPass.push(file);
+            } else {
+                callback(new Error("No location for " + file));
+                return;
+            }
+        }
+        var bothPasses = [].concat(firstPass).concat(secondPass);
+        for (var i = 0; i < bothPasses.length; i++) {
+            var file = bothPasses[i];
+            result = result || {};
+            _.merge(result, require(file));
+        }
+        if (!result) {
+            callback(new Error("local.amd.json not found"));
+        } else {
+            callback(null, result);
+        }
+    })
+};

+ 4 - 0
package.json

@@ -22,5 +22,9 @@
   },
   "engines": {
     "node": ">=0.8.0"
+  },
+  "dependencies": {
+    "lodash": "~2.4.1",
+    "findit": "~1.2.0"
   }
 }

+ 5 - 0
test/local-and-missing/.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDot": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/local-and-missing/amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooStripped": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/local-and-missing/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "foo": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/local-and-missing/missing.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooMissing": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/nothing/.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDot": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/nothing/amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooStripped": {"foo": "bar"}
+    }
+}

+ 62 - 1
test/produce.js

@@ -2,6 +2,67 @@
  * Created by Herby on 31. 5. 2014.
  */
 
-describe('#produceConfigObject', function () {
+var builder = require('../lib/config-builder'),
+    assert = require('assert'),
+    path = require('path');
+
+function fixture(fixturePath) {
+    return path.join(__dirname, fixturePath);
+}
+
+describe('#produceConfigObject merging', function () {
+    it('should include local.amd.json if none other is present', function (done) {
+        builder.produceConfigObject(fixture('single-local'), function (err, result) {
+            assert.ifError(err);
+            assert.deepEqual(result, {
+                config: {foo: {foo: "bar"}}
+            });
+            done();
+        });
+    });
+
+    it('should fail if foo.amd.json is present and there is no foo', function (done) {
+        builder.produceConfigObject(fixture('local-and-missing'), function (err, result) {
+            assert.ok(err);
+            done();
+        });
+    });
+
+    it('should fail if there is no applicable file', function (done) {
+        builder.produceConfigObject(fixture('nothing'), function (err, result) {
+            assert.ok(err);
+            done();
+        });
+    });
+
+    it('should include deep local.amd.json if none other is present', function (done) {
+        builder.produceConfigObject(fixture('single-deep-local'), function (err, result) {
+            assert.ifError(err);
+            assert.deepEqual(result, {
+                config: {fooDeep: {foo: "bar"}}
+            });
+            done();
+        });
+    });
+
+    it('should include both local.amd.json if root and deep are present', function (done) {
+        builder.produceConfigObject(fixture('two-locals'), function (err, result) {
+            assert.ifError(err);
+            assert.deepEqual(result, {
+                config: {foo: {foo: "bar"}, fooDeep: {foo: "bar"}}
+            });
+            done();
+        });
+    });
+
+    it('should include {root,deep}/local.amd.json first and {foo,bar}.amd.json afterwards given {foo,bar} dir is present', function (done) {
+        builder.produceConfigObject(fixture('two-locals-two-others'), function (err, result) {
+            assert.ifError(err);
+            assert.deepEqual(result, {
+                config: {a:2, b:2, c:2, d:2, e:1, f:1}
+            });
+            done();
+        });
+    });
 
 });

+ 5 - 0
test/single-deep-local/.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDot": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-deep-local/amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooStripped": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-deep-local/deep/.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDot": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-deep-local/deep/amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooStripped": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-deep-local/deep/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDeep": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-local/.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDot": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-local/amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooStripped": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/single-local/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "foo": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/two-locals-two-others/deep/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "a": 1, "b": 1, "e": 1
+    }
+}

+ 5 - 0
test/two-locals-two-others/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "c": 1, "d": 1, "f": 1
+    }
+}

+ 5 - 0
test/two-locals-two-others/other.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "b": 2, "c": 2
+    }
+}

+ 5 - 0
test/two-locals-two-others/other/deep.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "a": 2, "d": 2
+    }
+}

+ 5 - 0
test/two-locals/deep/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "fooDeep": {"foo": "bar"}
+    }
+}

+ 5 - 0
test/two-locals/local.amd.json

@@ -0,0 +1,5 @@
+{
+    "config": {
+        "foo": {"foo": "bar"}
+    }
+}