├── .gitignore
├── .jshintrc
├── .travis.yml
├── LICENSE
├── README.md
├── brand
├── logo.png
├── logo.svg
└── logoblue.svg
├── index.js
├── package.json
└── test
├── assets
├── folder.json
├── folder
│ ├── file.json
│ ├── nested.json
│ ├── nested
│ │ └── list.json
│ └── nonamesake
│ │ └── list.json
├── second.json
├── simple.json
└── third.json
└── index-test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "undef": true,
3 | "unused": true,
4 | "node": true,
5 | "esnext": true,
6 | "bitwise": true,
7 | "camelcase": true,
8 | "curly": true,
9 | "eqeqeq": true,
10 | "immed": true,
11 | "indent": 4,
12 | "latedef": true,
13 | "newcap": true,
14 | "noarg": true,
15 | "quotmark": "single",
16 | "regexp": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "globals": {
21 | "require": false,
22 | "module": false
23 | }
24 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.10"
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Jacobo Tabernero - jacobo@xarope.eu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | ========================================================================================================
3 |
4 | A better way to load big json config files in node.js apps.
5 |
6 | [deepjson.jacoborus.codes](http://deepjson.jacoborus.codes)
7 |
8 | [](https://travis-ci.org/jacoborus/deep-json)
9 |
10 |
11 | Why
12 | ---
13 |
14 | Sometimes config files grow to sizes that are difficult to handle, therefore it is desirable to distribute information in different files and folders rather than having a single big JSON file, you can split it up across multiple files (and directories) and deep.json puts it all back together. deep.json will also extend this object with the following files (and its trees) that you have passed as arguments.
15 |
16 |
17 | Installation
18 | ------------
19 |
20 | Install with **[npm](https://www.npmjs.org/package/deepjson)**
21 | ```
22 | $ npm install deepjson
23 | ```
24 |
25 | API
26 | ---
27 |
28 | ### deepjson( config1, config2, ... )
29 |
30 | Load all the json files passed as arguments, then extend them with json files under the folders with same name. Deepjson will return a object result of extend loaded files in order.
31 |
32 |
33 | **Parameters:**
34 |
35 | - **config** *String|Object*: path to file (with or without extension) or javascript object
36 | - **Return** *Object*: extended object
37 |
38 |
39 | Example
40 | -------
41 |
42 | .jsons and folders structure:
43 | ```
44 | ├── config.json: {"appname": "Fruits app", "port": 3000}
45 | ├── production.json: {"port": 4444}
46 | ├── config (folder)
47 | │ ├── SEO.json: {"description": "Fresh lemmons!" }
48 | │ ├── SEO (folder)
49 | │ ├── keywords.json: ["a", "big", "array"]
50 | ```
51 |
52 | ```js
53 | var deepjson = require( 'deepjson' );
54 |
55 | var defaultConfig = deepjson( 'config' );
56 | /* {
57 | appname: 'Fruits app',
58 | port: 3000,
59 | SEO: {
60 | description: 'Fresh lemmons!',
61 | keywords: ['a', 'big', 'array']
62 | }
63 | } */
64 |
65 |
66 | var productionConfig = deepjson( 'config', 'production' );
67 | /* {
68 | appname: 'Fruits app',
69 | port: 4444,
70 | SEO: {
71 | description: 'Fresh lemmons!',
72 | keywords: ['a', 'big', 'array']
73 | }
74 | } */
75 | ```
76 |
77 |
78 | Tests
79 | -----
80 |
81 | ```
82 | npm install && npm test
83 | ```
84 |
85 |
86 |
87 | ---
88 |
89 | © 2015 [Jacobo Tabernero](http://jacoborus.codes)
90 |
91 | Released under [MIT License](https://raw.github.com/jacoborus/deep-json/master/LICENSE)
92 |
--------------------------------------------------------------------------------
/brand/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacoborus/deep-json/d41f35cc67b21b87c39da42d264bbdcf891ec93c/brand/logo.png
--------------------------------------------------------------------------------
/brand/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
45 |
--------------------------------------------------------------------------------
/brand/logoblue.svg:
--------------------------------------------------------------------------------
1 |
2 |
59 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs'),
4 | path = require('path'),
5 | extend = require('extend');
6 |
7 | // return true if path is directory
8 | var isDir = function (dir) {
9 | return fs.existsSync(dir) ? fs.lstatSync( dir ).isDirectory() : false;
10 | };
11 |
12 | // return path of folder with same name as .json file if exists
13 | var getNamesake = function (file) {
14 | var folder = path.dirname(file) + '/' + path.basename( file, '.json' );
15 | return fs.existsSync(folder) && isDir(folder) ? folder : false;
16 | };
17 |
18 | // get the paths of files and folders inside a folder
19 | var getFolderElements = function (parent) {
20 | var elems = fs.readdirSync( parent ),
21 | d = {
22 | files : [],
23 | folders : []
24 | };
25 |
26 | // get files and folders paths
27 | elems.forEach( function (elem) {
28 | var el = parent + '/' + elem;
29 | if (!isDir( el )) {
30 | d.files.push( el );
31 | } else if (!fs.existsSync( el + '.json')) {
32 | // add folder only if has no namesake json
33 | d.folders.push( el );
34 | }
35 | });
36 |
37 | return d;
38 | };
39 |
40 |
41 | var getData = {
42 |
43 | // get file data and extend it with folder data of folder with same name
44 | file : function (file) {
45 | var config = require( file ),
46 | namesake = getNamesake( file );
47 |
48 | return namesake ? extend( config, getData.folder( namesake )) : config;
49 | },
50 |
51 | // get data from folders and files inside a folder
52 | folder : function (folder) {
53 | var elems = getFolderElements( folder ),
54 | result = {};
55 |
56 | // files
57 | elems.files.forEach( function (route) {
58 | // get object name
59 | var fileName = path.basename( route, '.json' );
60 | // assign object data from file
61 | result[ fileName ] = getData.file( route );
62 | });
63 |
64 | // no namesake folders
65 | elems.folders.forEach( function (route) {
66 | // get object name
67 | var fileName = path.basename( route );
68 | // assign data from folder
69 | result[ fileName ] = extend( result[ fileName ] || {}, getData.folder( route ));
70 | });
71 |
72 | return result;
73 | }
74 | };
75 |
76 |
77 | module.exports = function () {
78 | var configs = [],
79 | i;
80 |
81 | if (!arguments.length) {
82 | return {};
83 | }
84 |
85 | for (i in arguments) {
86 | if (typeof arguments[i] !== 'string') {
87 | if (typeof arguments[i] !== 'object' || typeof arguments[i].length !== 'undefined' || arguments[i] === null) {
88 | throw new Error( 'deep-json: bad file argument' );
89 | } else {
90 | configs[i] = arguments[i];
91 | }
92 | } else {
93 | configs[i] = getData.file( path.resolve( arguments[i] ));
94 | }
95 |
96 | }
97 |
98 | return extend.apply( {}, configs );
99 | };
100 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deepjson",
3 | "version": "1.1.2",
4 | "description": "A better way to load big json config files",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:jacoborus/deep-json.git"
12 | },
13 | "keywords": [
14 | "JSON",
15 | "config"
16 | ],
17 | "author": "Jacobo Tabernero -jacobo@xarope.eu",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/jacoborus/deep-json/issues"
21 | },
22 | "homepage": "http://deepjson.jacoborus.codes",
23 | "devDependencies": {
24 | "chai": "^3.3.0",
25 | "mocha": "^2.3.3"
26 | },
27 | "dependencies": {
28 | "extend": "^3.0.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/test/assets/folder.json:
--------------------------------------------------------------------------------
1 | {"main":1}
--------------------------------------------------------------------------------
/test/assets/folder/file.json:
--------------------------------------------------------------------------------
1 | {"third": 3}
--------------------------------------------------------------------------------
/test/assets/folder/nested.json:
--------------------------------------------------------------------------------
1 | {"cuatro": 4}
--------------------------------------------------------------------------------
/test/assets/folder/nested/list.json:
--------------------------------------------------------------------------------
1 | [1,2]
--------------------------------------------------------------------------------
/test/assets/folder/nonamesake/list.json:
--------------------------------------------------------------------------------
1 | [9,8,7]
--------------------------------------------------------------------------------
/test/assets/second.json:
--------------------------------------------------------------------------------
1 | {"main":2}
--------------------------------------------------------------------------------
/test/assets/simple.json:
--------------------------------------------------------------------------------
1 | {"main":1}
--------------------------------------------------------------------------------
/test/assets/third.json:
--------------------------------------------------------------------------------
1 | {"main":3}
--------------------------------------------------------------------------------
/test/index-test.js:
--------------------------------------------------------------------------------
1 | var expect = require('chai').expect,
2 | deepjson = require('../index.js'),
3 | fs = require('fs');
4 |
5 |
6 | describe( 'deepJSON', function () {
7 |
8 | it('Return an empty object if no arguments are passed', function () {
9 | expect( deepjson() ).to.be.a( 'object' );
10 | });
11 | it('Requires a master json file', function () {
12 | expect( function () {
13 | deepjson(4);
14 | }).to.throw( 'deep-json: bad file argument' );
15 | });
16 | it('Recover simple json files', function () {
17 | expect( deepjson( './test/assets/simple' ).main ).to.equal( 1 );
18 | });
19 | it('Extend values with folder named equal as json', function () {
20 | expect( deepjson( './test/assets/folder' ).file.third ).to.equal( 3 );
21 | });
22 | it('Extend values with folders with no json namesake', function () {
23 | expect( deepjson( './test/assets/folder' ).nonamesake.list[0] ).to.equal( 9 );
24 | });
25 | it('Extend values with folder and subfolders', function () {
26 | expect( deepjson( './test/assets/folder' ).nested.list[0] ).to.equal( 1 );
27 | });
28 | it('Extend first argument value with second one', function () {
29 | expect( deepjson( './test/assets/folder', './test/assets/second' ).main ).to.equal( 2 );
30 | });
31 | it('Extend second argument value with third one', function () {
32 | expect( deepjson( './test/assets/folder', './test/assets/second', './test/assets/third' ).main ).to.equal( 3 );
33 | });
34 | it('allow objects as params', function () {
35 | expect( deepjson({ secondary: 2 }, './test/assets/simple' ).secondary ).to.equal( 2 );
36 | });
37 | });
--------------------------------------------------------------------------------