From 42f4c2f514060041e76162c78156f1b941c255d9 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Fri, 7 May 2021 09:36:19 +0200 Subject: [PATCH] [Core] UiSettings Client: inline getRaw, remove deep merge (#85027) * inline getRow, remove deep merge * make sure uiSettings.getAll returns immutable result * update docs * Revert "update docs" This reverts commit a6c9bb33ed8360256c9929613696a599ac94d57b. * use freeze to speed up the process * apply Alejanro suggestion Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/core/server/ui_settings/types.ts | 1 - .../ui_settings/ui_settings_client.test.ts | 9 +++++ .../server/ui_settings/ui_settings_client.ts | 36 ++++++++++--------- .../field_formats/field_formats_service.ts | 3 +- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts index 0f13c82eed11a..5029f246367d3 100644 --- a/src/core/server/ui_settings/types.ts +++ b/src/core/server/ui_settings/types.ts @@ -5,7 +5,6 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { SavedObjectsClientContract } from '../saved_objects/types'; import { UiSettingsParams, UserProvidedValues, PublicUiSettingsParams } from '../../types'; export type { diff --git a/src/core/server/ui_settings/ui_settings_client.test.ts b/src/core/server/ui_settings/ui_settings_client.test.ts index 7f2147ea76beb..b73d25b7cf6e0 100644 --- a/src/core/server/ui_settings/ui_settings_client.test.ts +++ b/src/core/server/ui_settings/ui_settings_client.test.ts @@ -558,6 +558,15 @@ describe('ui settings', () => { bar: 'user-provided', }); }); + + it('throws if mutates the result of getAll()', async () => { + const { uiSettings } = setup({ esDocSource: {} }); + const result = await uiSettings.getAll(); + + expect(() => { + result.foo = 'bar'; + }).toThrow(); + }); }); describe('#get()', () => { diff --git a/src/core/server/ui_settings/ui_settings_client.ts b/src/core/server/ui_settings/ui_settings_client.ts index 3df48649781e9..ee0dcbea2a9aa 100644 --- a/src/core/server/ui_settings/ui_settings_client.ts +++ b/src/core/server/ui_settings/ui_settings_client.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { defaultsDeep, omit } from 'lodash'; +import { omit } from 'lodash'; import { SavedObjectsErrorHelpers } from '../saved_objects'; import { SavedObjectsClientContract } from '../saved_objects/types'; @@ -35,10 +35,7 @@ interface UserProvidedValue { isOverridden?: boolean; } -type UiSettingsRawValue = UiSettingsParams & UserProvidedValue; - type UserProvided = Record>; -type UiSettingsRaw = Record; export class UiSettingsClient implements IUiSettingsClient { private readonly type: UiSettingsServiceOptions['type']; @@ -47,6 +44,7 @@ export class UiSettingsClient implements IUiSettingsClient { private readonly savedObjectsClient: UiSettingsServiceOptions['savedObjectsClient']; private readonly overrides: NonNullable; private readonly defaults: NonNullable; + private readonly defaultValues: Record; private readonly log: Logger; private readonly cache: Cache; @@ -56,10 +54,15 @@ export class UiSettingsClient implements IUiSettingsClient { this.id = id; this.buildNum = buildNum; this.savedObjectsClient = savedObjectsClient; - this.defaults = defaults; this.overrides = overrides; this.log = log; this.cache = new Cache(); + this.defaults = defaults; + const defaultValues: Record = {}; + Object.keys(this.defaults).forEach((key) => { + defaultValues[key] = this.defaults[key].value; + }); + this.defaultValues = defaultValues; } getRegistered() { @@ -72,17 +75,21 @@ export class UiSettingsClient implements IUiSettingsClient { async get(key: string): Promise { const all = await this.getAll(); - return all[key]; + return all[key] as T; } async getAll() { - const raw = await this.getRaw(); + const result = { ...this.defaultValues }; - return Object.keys(raw).reduce((all, key) => { - const item = raw[key]; - all[key] = ('userValue' in item ? item.userValue : item.value) as T; - return all; - }, {} as Record); + const userProvided = await this.getUserProvided(); + Object.keys(userProvided).forEach((key) => { + if (userProvided[key].userValue !== undefined) { + result[key] = userProvided[key].userValue; + } + }); + + Object.freeze(result); + return result as Record; } async getUserProvided(): Promise> { @@ -142,11 +149,6 @@ export class UiSettingsClient implements IUiSettingsClient { } } - private async getRaw(): Promise { - const userProvided = await this.getUserProvided(); - return defaultsDeep({}, userProvided, this.defaults); - } - private validateKey(key: string, value: unknown) { const definition = this.defaults[key]; if (value === null || definition === undefined) return; diff --git a/src/plugins/data/server/field_formats/field_formats_service.ts b/src/plugins/data/server/field_formats/field_formats_service.ts index 70bb93f13ca5f..fa94e5dcef9cf 100644 --- a/src/plugins/data/server/field_formats/field_formats_service.ts +++ b/src/plugins/data/server/field_formats/field_formats_service.ts @@ -33,8 +33,9 @@ export class FieldFormatsService { return { fieldFormatServiceFactory: async (uiSettings: IUiSettingsClient) => { const fieldFormatsRegistry = new FieldFormatsRegistry(); - const uiConfigs = await uiSettings.getAll(); + const coreUiConfigs = await uiSettings.getAll(); const registeredUiSettings = uiSettings.getRegistered(); + const uiConfigs = { ...coreUiConfigs }; Object.keys(registeredUiSettings).forEach((key) => { if (has(uiConfigs, key) && registeredUiSettings[key].type === 'json') {