Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] UiSettings Client: inline getRaw, remove deep merge #85027

Merged
merged 12 commits into from
May 7, 2021
1 change: 0 additions & 1 deletion src/core/server/ui_settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions src/core/server/ui_settings/ui_settings_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()', () => {
Expand Down
36 changes: 19 additions & 17 deletions src/core/server/ui_settings/ui_settings_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -35,10 +35,7 @@ interface UserProvidedValue<T = unknown> {
isOverridden?: boolean;
}

type UiSettingsRawValue = UiSettingsParams & UserProvidedValue;

type UserProvided<T = unknown> = Record<string, UserProvidedValue<T>>;
type UiSettingsRaw = Record<string, UiSettingsRawValue>;

export class UiSettingsClient implements IUiSettingsClient {
private readonly type: UiSettingsServiceOptions['type'];
Expand All @@ -47,6 +44,7 @@ export class UiSettingsClient implements IUiSettingsClient {
private readonly savedObjectsClient: UiSettingsServiceOptions['savedObjectsClient'];
private readonly overrides: NonNullable<UiSettingsServiceOptions['overrides']>;
private readonly defaults: NonNullable<UiSettingsServiceOptions['defaults']>;
private readonly defaultValues: Record<string, unknown>;
private readonly log: Logger;
private readonly cache: Cache;

Expand All @@ -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<string, unknown> = {};
Object.keys(this.defaults).forEach((key) => {
defaultValues[key] = this.defaults[key].value;
});
this.defaultValues = defaultValues;
}

getRegistered() {
Expand All @@ -72,17 +75,21 @@ export class UiSettingsClient implements IUiSettingsClient {

async get<T = any>(key: string): Promise<T> {
const all = await this.getAll();
return all[key];
return all[key] as T;
}

async getAll<T = any>() {
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<string, T>);
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<string, T>;
}

async getUserProvided<T = unknown>(): Promise<UserProvided<T>> {
Expand Down Expand Up @@ -142,11 +149,6 @@ export class UiSettingsClient implements IUiSettingsClient {
}
}

private async getRaw(): Promise<UiSettingsRaw> {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down