diff --git a/lib/core/utils.js b/lib/core/utils.js index 445dead72e..6f6a5f70fd 100644 --- a/lib/core/utils.js +++ b/lib/core/utils.js @@ -9,18 +9,28 @@ module.exports = { safeParseURL, }; -function convertObject(obj, ignore) { - if (!is.array(ignore)) ignore = [ ignore ]; +function convertObject(obj, ignore, ignoreKeyPaths) { + if (!is.array(ignore)) { + ignore = [ ignore ]; + } + if (!is.array(ignoreKeyPaths)) { + ignoreKeyPaths = ignoreKeyPaths ? [ ignoreKeyPaths ] : []; + } + _convertObject(obj, ignore, ignoreKeyPaths, ''); +} + +function _convertObject(obj, ignore, ignoreKeyPaths, keyPath) { for (const key of Object.keys(obj)) { - obj[key] = convertValue(key, obj[key], ignore); + obj[key] = convertValue(key, obj[key], ignore, ignoreKeyPaths, keyPath ? `${keyPath}.${key}` : key); } return obj; } -function convertValue(key, value, ignore) { +function convertValue(key, value, ignore, ignoreKeyPaths, keyPath) { if (is.nullOrUndefined(value)) return value; let hit = false; + let hitKeyPath = false; for (const matchKey of ignore) { if (is.string(matchKey) && matchKey === key) { hit = true; @@ -30,7 +40,13 @@ function convertValue(key, value, ignore) { break; } } - if (!hit) { + for (const matchKeyPath of ignoreKeyPaths) { + if (is.string(matchKeyPath) && keyPath === matchKeyPath) { + hitKeyPath = true; + break; + } + } + if (!hit && !hitKeyPath) { if (is.symbol(value) || is.regExp(value)) return value.toString(); if (is.primitive(value) || is.array(value)) return value; } @@ -38,7 +54,10 @@ function convertValue(key, value, ignore) { // only convert recursively when it's a plain object, // o = {} if (Object.getPrototypeOf(value) === Object.prototype) { - return convertObject(value, ignore); + if (hitKeyPath) { + return ''; + } + return _convertObject(value, ignore, ignoreKeyPaths, keyPath); } // support class diff --git a/lib/egg.js b/lib/egg.js index 8c1b4e9064..55d9fbd63f 100644 --- a/lib/egg.js +++ b/lib/egg.js @@ -395,8 +395,15 @@ class EggApplication extends EggCore { ignoreList = []; } + let ignoreKeyPaths; + try { + ignoreKeyPaths = this.config.dump.ignoreKeyPaths; + } catch (e) { + ignoreKeyPaths = {}; + } + const json = extend(true, {}, { config: this.config, plugins: this.loader.allPlugins, appInfo: this.loader.appInfo }); - utils.convertObject(json, ignoreList); + utils.convertObject(json, ignoreList, ignoreKeyPaths ? Object.keys(ignoreKeyPaths) : []); return { config: json, meta: this.loader.configMeta, diff --git a/test/fixtures/apps/dump-ignore-key-path/config/config.default.js b/test/fixtures/apps/dump-ignore-key-path/config/config.default.js new file mode 100644 index 0000000000..1839bc21cd --- /dev/null +++ b/test/fixtures/apps/dump-ignore-key-path/config/config.default.js @@ -0,0 +1,16 @@ +exports.withKeyPaths = { + inner: { + key1: { + nested: true, + }, + }, + key2: 'str', +}; + +exports.dump = { + ignoreKeyPaths: { + 'config.withKeyPaths.key2': true, + }, +}; + +exports.keys = 'test key'; diff --git a/test/fixtures/apps/dump-ignore-key-path/config/config.unittest.js b/test/fixtures/apps/dump-ignore-key-path/config/config.unittest.js new file mode 100644 index 0000000000..dd7e76f86b --- /dev/null +++ b/test/fixtures/apps/dump-ignore-key-path/config/config.unittest.js @@ -0,0 +1,5 @@ +exports.dump = { + ignoreKeyPaths: { + 'config.withKeyPaths.inner.key1': true, + }, +}; diff --git a/test/fixtures/apps/dump-ignore-key-path/config/plugin.js b/test/fixtures/apps/dump-ignore-key-path/config/plugin.js new file mode 100644 index 0000000000..bcb4215c28 --- /dev/null +++ b/test/fixtures/apps/dump-ignore-key-path/config/plugin.js @@ -0,0 +1,3 @@ +'use strict'; + +exports.static = false; diff --git a/test/fixtures/apps/dump-ignore-key-path/package.json b/test/fixtures/apps/dump-ignore-key-path/package.json new file mode 100644 index 0000000000..cfbe721f9d --- /dev/null +++ b/test/fixtures/apps/dump-ignore-key-path/package.json @@ -0,0 +1,3 @@ +{ + "name": "dumpconfig" +} diff --git a/test/lib/core/utils.test.js b/test/lib/core/utils.test.js index 35683ab8f6..6acf1beaab 100644 --- a/test/lib/core/utils.test.js +++ b/test/lib/core/utils.test.js @@ -155,6 +155,66 @@ describe('test/lib/core/utils.test.js', () => { assert(obj.anonymousClassWithPropName === ''); assert(obj[''] === ''); }); + + it('should support keyPath', () => { + const obj = { + plainObj: 'Plain', + Id: 1, + recursiveObj: { + value1: 'string', + value2: 1, + innerObj: { + key1: true, + }, + }, + arr: [ + { + v1: 'str', + }, + ], + }; + utils.convertObject(obj, [], [ 'id', 'recursiveObj.value2', 'recursiveObj.innerObj', 'arr' ]); + assert.deepEqual(obj, { + plainObj: 'Plain', + Id: 1, + recursiveObj: { + value1: 'string', + value2: '', + innerObj: '', + }, + arr: '', + }); + }); + + it('should hit key and keyPath simultaneously work', () => { + const obj = { + recursiveObj: { + value1: 'string', + value2: 1, + innerObj: { + key1: true, + }, + }, + arr: [ + { + v1: 'str', + }, + ], + }; + utils.convertObject( + obj, + [ 'arr', 'value2', 'innerObj' ], + [ 'recursiveObj.value2', 'recursiveObj.innerObj', 'arr' ] + ); + assert.deepEqual(obj, { + recursiveObj: { + value1: 'string', + value2: '', + innerObj: '', + }, + arr: '', + }); + }); }); describe('safeParseURL()', () => { diff --git a/test/lib/egg.test.js b/test/lib/egg.test.js index 66ab0ed35f..672a1ae97e 100644 --- a/test/lib/egg.test.js +++ b/test/lib/egg.test.js @@ -254,6 +254,26 @@ describe('test/lib/egg.test.js', () => { }); }); + describe('dumpConfig() ignore key path', () => { + const baseDir = utils.getFilepath('apps/dump-ignore-key-path'); + let app; + before(() => { + app = utils.app('apps/dump-ignore-key-path'); + return app.ready(); + }); + after(() => app.close()); + + it('should ignore key path', () => { + const json = require(path.join(baseDir, 'run/application_config.json')); + assert.deepEqual(json.config.withKeyPaths, { + inner: { + key1: '', + }, + key2: '', + }); + }); + }); + describe('custom config from env', () => { let app; let baseDir;