From 728c34fc3c6a5d605b48b9c8ac56e18533c67c96 Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 30 Apr 2020 23:58:46 -0700 Subject: [PATCH] [legacy/server/config] remove unnecessary deps for simple helper (#64954) * [legacy/server/config] remove unnecessary deps for simple helper * remove unnecessary change * expand test coverage a smidge * explode dot-separated keys * add a test for really deep keys Co-authored-by: spalger --- src/legacy/server/config/config.js | 2 +- src/legacy/server/config/explode_by.js | 37 ------ src/legacy/server/config/explode_by.test.js | 48 -------- src/legacy/server/config/override.js | 28 ----- src/legacy/server/config/override.test.js | 44 ------- src/legacy/server/config/override.test.ts | 130 ++++++++++++++++++++ src/legacy/server/config/override.ts | 52 ++++++++ 7 files changed, 183 insertions(+), 158 deletions(-) delete mode 100644 src/legacy/server/config/explode_by.js delete mode 100644 src/legacy/server/config/explode_by.test.js delete mode 100644 src/legacy/server/config/override.js delete mode 100644 src/legacy/server/config/override.test.js create mode 100644 src/legacy/server/config/override.test.ts create mode 100644 src/legacy/server/config/override.ts diff --git a/src/legacy/server/config/config.js b/src/legacy/server/config/config.js index c31ded608dd3..b186071edeaf 100644 --- a/src/legacy/server/config/config.js +++ b/src/legacy/server/config/config.js @@ -19,7 +19,7 @@ import Joi from 'joi'; import _ from 'lodash'; -import override from './override'; +import { override } from './override'; import createDefaultSchema from './schema'; import { unset, deepCloneWithBuffers as clone, IS_KIBANA_DISTRIBUTABLE } from '../../utils'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths diff --git a/src/legacy/server/config/explode_by.js b/src/legacy/server/config/explode_by.js deleted file mode 100644 index 46347feca550..000000000000 --- a/src/legacy/server/config/explode_by.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -export default function(dot, flatObject) { - const fullObject = {}; - _.each(flatObject, function(value, key) { - const keys = key.split(dot); - (function walk(memo, keys, value) { - const _key = keys.shift(); - if (keys.length === 0) { - memo[_key] = value; - } else { - if (!memo[_key]) memo[_key] = {}; - walk(memo[_key], keys, value); - } - })(fullObject, keys, value); - }); - return fullObject; -} diff --git a/src/legacy/server/config/explode_by.test.js b/src/legacy/server/config/explode_by.test.js deleted file mode 100644 index 741edba27d32..000000000000 --- a/src/legacy/server/config/explode_by.test.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import explodeBy from './explode_by'; - -describe('explode_by(dot, flatObject)', function() { - it('should explode a flatten object with dots', function() { - const flatObject = { - 'test.enable': true, - 'test.hosts': ['host-01', 'host-02'], - }; - expect(explodeBy('.', flatObject)).toEqual({ - test: { - enable: true, - hosts: ['host-01', 'host-02'], - }, - }); - }); - - it('should explode a flatten object with slashes', function() { - const flatObject = { - 'test/enable': true, - 'test/hosts': ['host-01', 'host-02'], - }; - expect(explodeBy('/', flatObject)).toEqual({ - test: { - enable: true, - hosts: ['host-01', 'host-02'], - }, - }); - }); -}); diff --git a/src/legacy/server/config/override.js b/src/legacy/server/config/override.js deleted file mode 100644 index bab9387ac006..000000000000 --- a/src/legacy/server/config/override.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import explodeBy from './explode_by'; -import { getFlattenedObject } from '../../../core/utils'; - -export default function(target, source) { - const _target = getFlattenedObject(target); - const _source = getFlattenedObject(source); - return explodeBy('.', _.defaults(_source, _target)); -} diff --git a/src/legacy/server/config/override.test.js b/src/legacy/server/config/override.test.js deleted file mode 100644 index 331c586e28a8..000000000000 --- a/src/legacy/server/config/override.test.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import override from './override'; - -describe('override(target, source)', function() { - it('should override the values form source to target', function() { - const target = { - test: { - enable: true, - host: ['host-01', 'host-02'], - client: { - type: 'sql', - }, - }, - }; - const source = { test: { client: { type: 'nosql' } } }; - expect(override(target, source)).toEqual({ - test: { - enable: true, - host: ['host-01', 'host-02'], - client: { - type: 'nosql', - }, - }, - }); - }); -}); diff --git a/src/legacy/server/config/override.test.ts b/src/legacy/server/config/override.test.ts new file mode 100644 index 000000000000..4e21a88e79e6 --- /dev/null +++ b/src/legacy/server/config/override.test.ts @@ -0,0 +1,130 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { override } from './override'; + +describe('override(target, source)', function() { + it('should override the values form source to target', function() { + const target = { + test: { + enable: true, + host: ['something else'], + client: { + type: 'sql', + }, + }, + }; + + const source = { + test: { + host: ['host-01', 'host-02'], + client: { + type: 'nosql', + }, + foo: { + bar: { + baz: 1, + }, + }, + }, + }; + + expect(override(target, source)).toMatchInlineSnapshot(` + Object { + "test": Object { + "client": Object { + "type": "nosql", + }, + "enable": true, + "foo": Object { + "bar": Object { + "baz": 1, + }, + }, + "host": Array [ + "host-01", + "host-02", + ], + }, + } + `); + }); + + it('does not mutate arguments', () => { + const target = { + foo: { + bar: 1, + baz: 1, + }, + }; + + const source = { + foo: { + bar: 2, + }, + box: 2, + }; + + expect(override(target, source)).toMatchInlineSnapshot(` + Object { + "box": 2, + "foo": Object { + "bar": 2, + "baz": 1, + }, + } + `); + expect(target).not.toHaveProperty('box'); + expect(source.foo).not.toHaveProperty('baz'); + }); + + it('explodes keys with dots in them', () => { + const target = { + foo: { + bar: 1, + }, + 'baz.box.boot.bar.bar': 20, + }; + + const source = { + 'foo.bar': 2, + 'baz.box.boot': { + 'bar.foo': 10, + }, + }; + + expect(override(target, source)).toMatchInlineSnapshot(` + Object { + "baz": Object { + "box": Object { + "boot": Object { + "bar": Object { + "bar": 20, + "foo": 10, + }, + }, + }, + }, + "foo": Object { + "bar": 2, + }, + } + `); + }); +}); diff --git a/src/legacy/server/config/override.ts b/src/legacy/server/config/override.ts new file mode 100644 index 000000000000..3dd7d6201600 --- /dev/null +++ b/src/legacy/server/config/override.ts @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const isObject = (v: any): v is Record => + typeof v === 'object' && v !== null && !Array.isArray(v); + +const assignDeep = (target: Record, source: Record) => { + for (let [key, value] of Object.entries(source)) { + // unwrap dot-separated keys + if (key.includes('.')) { + const [first, ...others] = key.split('.'); + key = first; + value = { [others.join('.')]: value }; + } + + if (isObject(value)) { + if (!target.hasOwnProperty(key)) { + target[key] = {}; + } + + assignDeep(target[key], value); + } else { + target[key] = value; + } + } +}; + +export const override = (...sources: Array>): Record => { + const result = {}; + + for (const object of sources) { + assignDeep(result, object); + } + + return result; +};