diff --git a/.gitignore b/.gitignore index 5148e52..e3a9f6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,4 @@ -# Logs -logs -*.log -npm-debug.log* - -# Runtime data -pids -*.pid -*.seed - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories node_modules -jspm_packages - -# Optional npm cache directory -.npm - -# Optional REPL history -.node_repl_history +lib +var +!var/.gitkeep diff --git a/index.js b/index.js new file mode 100644 index 0000000..08e9a21 --- /dev/null +++ b/index.js @@ -0,0 +1,12 @@ +'use strict'; + +let fs = require('fs'), + packageJsonPath = `${process.cwd()}/package.json`, + packageJsonContent = fs.readFileSync(packageJsonPath), +/** @param {{extra: {node_parameter_handler: []}}} content */ + packageJson = JSON.parse(packageJsonContent), + Processor = require('./src/processor'), + processor = new Processor(packageJson.extra.node_parameter_handler, process.cwd()); + +processor.process(); +processor.write(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..b94db40 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "node.js-parameter-handler", + "version": "0.1.0", + "description": "build .json files which can be used as settings", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/explore-node-js/node.js-parameter-handler.git" + }, + "keywords": [ + "config handler, parameter handler" + ], + "author": "Eugene Matvejev ", + "license": "MIT", + "bugs": { + "url": "https://github.com/explore-node-js/node.js-parameter-handler/issues" + }, + "homepage": "https://github.com/explore-node-js/node.js-parameter-handler#readme", + "dependencies": { + "deepmerge": "^1.3.1", + "jsonfile": "^2.4.0" + }, + "devDependencies": { + "jest": "^18.1.0" + }, + "scripts": { + "test": "node node_modules/jest/bin/jest.js" + } +} diff --git a/src/file.js b/src/file.js new file mode 100644 index 0000000..d81a6a6 --- /dev/null +++ b/src/file.js @@ -0,0 +1,2 @@ +module.exports = class File { +} diff --git a/src/processor.js b/src/processor.js new file mode 100644 index 0000000..6cc2e58 --- /dev/null +++ b/src/processor.js @@ -0,0 +1,108 @@ +let fs = require('fs'), + deepmerge = require('deepmerge'), + File = require('./file'); + +module.exports = class Processor { + constructor(config, cwd) { + this.config = config; + this.cwd = cwd; + } + + process() { + this.files = []; + + this.config.forEach(config => { + let file = this.processFile(config); + + this.files.push(file); + }) + } + + write() { + this.files.forEach(file => fs.writeFile(file.output, JSON.stringify(file.content, null, 2), 'UTF-8')); + } + + /** + * @param {{envMap: {}, output: string, source: string}} config + * + * @returns {*} + */ + processFile(config) { + let file = new File(); + + let pathSource = this.resolvePath(config.source), + pathOutput = this.resolvePath(config.output); + + let packageJsonPath = this.resolvePath(pathSource), + packageJsonContent = fs.readFileSync(packageJsonPath); + + /** @param {{extra: {}}} content */ + let packageJson = JSON.parse(packageJsonContent), + solvedJson = this.resolveOverwritten(config.envMap), + completedJson = this.constructor.getMergedData(packageJson, solvedJson); + + file.source = pathSource; + file.output = pathOutput; + file.content = completedJson; + + return file; + } + + /** + * @param {string} path + */ + resolvePath(path) { + if ('/' === path.charAt(0)) { + return path; + } + + return `${this.cwd}/${path}`; + } + + resolveOverwritten(envMapping) { + let object = {}; + + for (let abstractPath of Object.keys(envMapping)) { + let envVariable = envMapping[abstractPath], + value = this.constructor.getEnvironmentValue(envVariable); + + this.constructor.overwriteObjectFieldValue(abstractPath, value, object) + } + + return object; + } + + static getEnvironmentValue(index) { + return process.env[index] || undefined; + } + + static getMergedData(data, overwrittenData) { + return deepmerge(data, overwrittenData); + } + + static overwriteObjectFieldValue(abstractPath, value, object, delimiter) { + if (undefined === value) { + return; + } + + delimiter = undefined !== delimiter ? delimiter : '.'; + + let indexes = abstractPath.split(delimiter), + lastPartIndex = indexes.length - 1; + + for (let i = 0; i <= lastPartIndex; i++) { + let index = indexes[i]; + + if (i === lastPartIndex) { + object[index] = value; + break; + } + + if (undefined === object[index]) { + object[index] = {}; + } + + object = object[index]; + } + } +}; diff --git a/tests/fixtures/package.json b/tests/fixtures/package.json new file mode 100644 index 0000000..eedb411 --- /dev/null +++ b/tests/fixtures/package.json @@ -0,0 +1,15 @@ +{ + "extra": { + "node_parameter_handler": [ + { + "source": "tests/fixtures/settings.json.dist", + "output": "var/settings.json", + "envMap": { + "touched": "BASE_URL", + "test.touched": "PWD", + "test.test.touched": "HOME" + } + } + ] + } +} diff --git a/tests/fixtures/settings.json.dist b/tests/fixtures/settings.json.dist new file mode 100644 index 0000000..86cf4dc --- /dev/null +++ b/tests/fixtures/settings.json.dist @@ -0,0 +1,12 @@ +{ + "touched": "to be replaced", + "untouched": "untouched", + "test": { + "touched": "to be replaced", + "untouched": "untouched", + "test": { + "touched": "to be replaced", + "untouched": "untouched" + } + } +} diff --git a/tests/processor.test.js b/tests/processor.test.js new file mode 100644 index 0000000..12467b6 --- /dev/null +++ b/tests/processor.test.js @@ -0,0 +1,17 @@ +"use strict"; + +const Processor = require('../src/processor'); +const config = require('./fixtures/package.json').extra.node_parameter_handler; +const cwd = process.cwd(); + +describe('processor', () => { + describe('::resolvePath', () => { + const processor = new Processor(config, cwd); + + [ '/', 'test', 'test/', 'test/test', '/test/test' ].forEach(path => { + it(`should be converted '${path}' to absolute path`, () => { + expect(processor.resolvePath(path)).toMatch(/^\/.*/); + }) + }); + }) +}); diff --git a/var/.gitkeep b/var/.gitkeep new file mode 100644 index 0000000..e69de29