diff --git a/src/core_plugins/kibana/index.js b/src/core_plugins/kibana/index.js
index 611d7cbd215f1..b3fe0bc2dd07e 100644
--- a/src/core_plugins/kibana/index.js
+++ b/src/core_plugins/kibana/index.js
@@ -13,6 +13,7 @@ import { registerSuggestionsApi } from './server/routes/api/suggestions';
import * as systemApi from './server/lib/system_api';
import handleEsError from './server/lib/handle_es_error';
import mappings from './mappings.json';
+import { getUiSettingDefaults } from './ui_setting_defaults';
import { injectVars } from './inject_vars';
@@ -106,7 +107,9 @@ export default function (kibana) {
translations: [
resolve(__dirname, './translations/en.json')
],
- mappings
+
+ mappings,
+ uiSettingDefaults: getUiSettingDefaults(),
},
preInit: async function (server) {
diff --git a/src/ui/ui_settings/defaults.js b/src/core_plugins/kibana/ui_setting_defaults.js
similarity index 89%
rename from src/ui/ui_settings/defaults.js
rename to src/core_plugins/kibana/ui_setting_defaults.js
index 3890333f23507..65947a341cf66 100644
--- a/src/ui/ui_settings/defaults.js
+++ b/src/core_plugins/kibana/ui_setting_defaults.js
@@ -1,6 +1,6 @@
import moment from 'moment-timezone';
-export function getDefaultSettings() {
+export function getUiSettingDefaults() {
const weekdays = moment.weekdays().slice();
const [defaultWeekday] = weekdays;
@@ -283,47 +283,6 @@ export function getDefaultSettings() {
value: 2000,
description: 'The maximum number of buckets a single datasource can return'
},
- // Timelion stuff
- 'timelion:showTutorial': {
- value: false,
- description: 'Should I show the tutorial by default when entering the timelion app?'
- },
- 'timelion:es.timefield': {
- value: '@timestamp',
- description: 'Default field containing a timestamp when using .es()'
- },
- 'timelion:es.default_index': {
- value: '_all',
- description: 'Default elasticsearch index to search with .es()'
- },
- 'timelion:target_buckets': {
- value: 200,
- description: 'The number of buckets to shoot for when using auto intervals'
- },
- 'timelion:max_buckets': {
- value: 2000,
- description: 'The maximum number of buckets a single datasource can return'
- },
- 'timelion:default_columns': {
- value: 2,
- description: 'Number of columns on a timelion sheet by default'
- },
- 'timelion:default_rows': {
- value: 2,
- description: 'Number of rows on a timelion sheet by default'
- },
- 'timelion:min_interval': {
- value: '1ms',
- description: 'The smallest interval that will be calculated when using "auto"'
- },
- 'timelion:graphite.url': {
- value: 'https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite',
- description: '[experimental] The URL of your graphite host'
- },
- 'timelion:quandl.key': {
- value: 'someKeyHere',
- description: '[experimental] Your API key from www.quandl.com'
- },
'state:storeInSessionStorage': {
value: false,
description: 'The URL can sometimes grow to be too large for some browsers to ' +
diff --git a/src/core_plugins/tests_bundle/index.js b/src/core_plugins/tests_bundle/index.js
index e78f4bd008df9..335457290293e 100644
--- a/src/core_plugins/tests_bundle/index.js
+++ b/src/core_plugins/tests_bundle/index.js
@@ -1,5 +1,4 @@
import { union } from 'lodash';
-import { getDefaultSettings } from '../../ui/ui_settings/defaults';
import findSourceFiles from './find_source_files';
import { fromRoot } from '../../utils';
@@ -57,7 +56,11 @@ export default (kibana) => {
});
}
- env.defaultUiSettings = getDefaultSettings();
+ env.defaultUiSettings = plugins.kbnServer.uiExports.consumers
+ // find the first uiExportsConsumer that has a getUiSettingDefaults method
+ // See src/ui/ui_settings/ui_exports_consumer.js
+ .find(consumer => typeof consumer.getUiSettingDefaults === 'function')
+ .getUiSettingDefaults();
return new UiBundle({
id: 'tests',
diff --git a/src/core_plugins/timelion/index.js b/src/core_plugins/timelion/index.js
index c510267c823ca..aee3cb9a24f90 100644
--- a/src/core_plugins/timelion/index.js
+++ b/src/core_plugins/timelion/index.js
@@ -36,7 +36,50 @@ export default function (kibana) {
visTypes: [
'plugins/timelion/vis'
],
- mappings: require('./mappings.json')
+ mappings: require('./mappings.json'),
+
+ uiSettingDefaults: {
+ 'timelion:showTutorial': {
+ value: false,
+ description: 'Should I show the tutorial by default when entering the timelion app?'
+ },
+ 'timelion:es.timefield': {
+ value: '@timestamp',
+ description: 'Default field containing a timestamp when using .es()'
+ },
+ 'timelion:es.default_index': {
+ value: '_all',
+ description: 'Default elasticsearch index to search with .es()'
+ },
+ 'timelion:target_buckets': {
+ value: 200,
+ description: 'The number of buckets to shoot for when using auto intervals'
+ },
+ 'timelion:max_buckets': {
+ value: 2000,
+ description: 'The maximum number of buckets a single datasource can return'
+ },
+ 'timelion:default_columns': {
+ value: 2,
+ description: 'Number of columns on a timelion sheet by default'
+ },
+ 'timelion:default_rows': {
+ value: 2,
+ description: 'Number of rows on a timelion sheet by default'
+ },
+ 'timelion:min_interval': {
+ value: '1ms',
+ description: 'The smallest interval that will be calculated when using "auto"'
+ },
+ 'timelion:graphite.url': {
+ value: 'https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite',
+ description: '[experimental] The URL of your graphite host'
+ },
+ 'timelion:quandl.key': {
+ value: 'someKeyHere',
+ description: '[experimental] Your API key from www.quandl.com'
+ }
+ }
},
init: require('./init.js'),
});
diff --git a/src/server/kbn_server.js b/src/server/kbn_server.js
index e4d18a7b8afb9..570b2fdec4a1f 100644
--- a/src/server/kbn_server.js
+++ b/src/server/kbn_server.js
@@ -15,7 +15,7 @@ import pluginsScanMixin from './plugins/scan';
import pluginsCheckEnabledMixin from './plugins/check_enabled';
import pluginsCheckVersionMixin from './plugins/check_version';
import configCompleteMixin from './config/complete';
-import uiMixin, { uiSettingsMixin } from '../ui';
+import uiMixin from '../ui';
import optimizeMixin from '../optimize';
import pluginsInitializeMixin from './plugins/initialize';
import { indexPatternsMixin } from './index_patterns';
@@ -66,9 +66,6 @@ export default class KbnServer {
// setup saved object routes
savedObjectsMixin,
- // setup server.uiSettings
- uiSettingsMixin,
-
// ensure that all bundles are built, or that the
// lazy bundle server is running
optimizeMixin,
diff --git a/src/ui/index.js b/src/ui/index.js
index 8d4eb73c85117..1a978dc86f291 100644
--- a/src/ui/index.js
+++ b/src/ui/index.js
@@ -9,13 +9,15 @@ import UiBundleCollection from './ui_bundle_collection';
import UiBundlerEnv from './ui_bundler_env';
import { UiI18n } from './ui_i18n';
-export { uiSettingsMixin } from './ui_settings';
+import { uiSettingsMixin } from './ui_settings';
export default async (kbnServer, server, config) => {
const uiExports = kbnServer.uiExports = new UiExports({
urlBasePath: config.get('server.basePath')
});
+ await kbnServer.mixin(uiSettingsMixin);
+
const uiI18n = kbnServer.uiI18n = new UiI18n(config.get('i18n.defaultLocale'));
uiI18n.addUiExportConsumer(uiExports);
diff --git a/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js b/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js
index 11159061ef74f..a81d7d6d8d3a3 100644
--- a/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js
+++ b/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js
@@ -51,6 +51,7 @@ describe('uiSettingsMixin()', () => {
const kbnServer = {
server,
config,
+ uiExports: { addConsumer: sinon.stub() },
status: new ServerStatus(server),
ready: sinon.stub().returns(readyPromise),
};
@@ -133,9 +134,14 @@ describe('uiSettingsMixin()', () => {
sandbox.stub(uiSettingsServiceFactoryNS, 'uiSettingsServiceFactory');
sinon.assert.notCalled(uiSettingsServiceFactory);
- const football = {};
- decorations.server.uiSettingsServiceFactory(football);
- sinon.assert.calledWith(uiSettingsServiceFactory, server, football);
+ decorations.server.uiSettingsServiceFactory({
+ foo: 'bar'
+ });
+ sinon.assert.calledOnce(uiSettingsServiceFactory);
+ sinon.assert.calledWithExactly(uiSettingsServiceFactory, server, {
+ foo: 'bar',
+ getDefaults: sinon.match.func,
+ });
});
});
@@ -168,7 +174,10 @@ describe('uiSettingsMixin()', () => {
sandbox.stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest');
decorations.request.getUiSettingsService();
- const readInterceptor = getUiSettingsServiceForRequest.firstCall.args[2];
+ const options = getUiSettingsServiceForRequest.firstCall.args[2];
+ expect(options).to.have.property('readInterceptor');
+
+ const { readInterceptor } = options;
expect(readInterceptor).to.be.a('function');
status.green();
diff --git a/src/ui/ui_settings/__tests__/ui_settings_service.js b/src/ui/ui_settings/__tests__/ui_settings_service.js
index c7706414b0a0c..ed121e004bc69 100644
--- a/src/ui/ui_settings/__tests__/ui_settings_service.js
+++ b/src/ui/ui_settings/__tests__/ui_settings_service.js
@@ -1,8 +1,8 @@
import { isEqual } from 'lodash';
import expect from 'expect.js';
import { errors as esErrors } from 'elasticsearch';
+import Chance from 'chance';
-import { getDefaultSettings } from '../defaults';
import { UiSettingsService } from '../ui_settings_service';
import { createCallClusterStub } from './lib';
@@ -10,10 +10,13 @@ import { createCallClusterStub } from './lib';
const INDEX = '.kibana';
const TYPE = 'config';
const ID = 'kibana-version';
+const chance = new Chance();
function setup(options = {}) {
const {
readInterceptor,
+ getDefaults,
+ defaults = {},
esDocSource = {},
callCluster = createCallClusterStub(INDEX, TYPE, ID, esDocSource)
} = options;
@@ -22,6 +25,7 @@ function setup(options = {}) {
index: INDEX,
type: TYPE,
id: ID,
+ getDefaults: getDefaults || (() => defaults),
readInterceptor,
callCluster,
});
@@ -114,34 +118,26 @@ describe('ui settings', () => {
});
describe('#getDefaults()', () => {
- it('is promised the default values', async () => {
- const {
- uiSettings
- } = setup();
- const defaults = await uiSettings.getDefaults();
- expect(isEqual(defaults, getDefaultSettings())).to.equal(true);
- });
-
-
- describe('defaults for formatters', async () => {
-
- const defaults = getDefaultSettings();
- const mapping = JSON.parse(defaults['format:defaultTypeMap'].value);
- const expected = {
- ip: { id: 'ip', params: {} },
- date: { id: 'date', params: {} },
- number: { id: 'number', params: {} },
- boolean: { id: 'boolean', params: {} },
- _source: { id: '_source', params: {} },
- _default_: { id: 'string', params: {} }
- };
+ it('returns a promise for the defaults', async () => {
+ const { uiSettings } = setup();
+ const promise = uiSettings.getDefaults();
+ expect(promise).to.be.a(Promise);
+ expect(await promise).to.eql({});
+ });
+ });
- Object.keys(mapping).forEach((dataType) => {
- it(`should configure ${dataType}`, () => {
- expect(expected.hasOwnProperty(dataType)).to.equal(true);
- expect(mapping[dataType].id).to.equal(expected[dataType].id);
- expect(JSON.stringify(mapping[dataType].params)).to.equal(JSON.stringify(expected[dataType].params));
- });
+ describe('getDefaults() argument', () => {
+ it('casts sync `getDefaults()` to promise', () => {
+ const getDefaults = () => ({ key: { value: chance.word() } });
+ const { uiSettings } = setup({ getDefaults });
+ expect(uiSettings.getDefaults()).to.be.a(Promise);
+ });
+
+ it('returns the defaults returned by getDefaults() argument', async () => {
+ const value = chance.word();
+ const { uiSettings } = setup({ defaults: { key: { value } } });
+ expect(await uiSettings.getDefaults()).to.eql({
+ key: { value }
});
});
});
@@ -244,27 +240,26 @@ describe('ui settings', () => {
it(`without user configuration it's equal to the defaults`, async () => {
const esDocSource = {};
- const { uiSettings } = setup({ esDocSource });
+ const defaults = { key: { value: chance.word() } };
+ const { uiSettings } = setup({ esDocSource, defaults });
const result = await uiSettings.getRaw();
- expect(isEqual(result, getDefaultSettings())).to.equal(true);
+ expect(result).to.eql(defaults);
});
it(`user configuration gets merged with defaults`, async () => {
const esDocSource = { foo: 'bar' };
- const { uiSettings } = setup({ esDocSource });
+ const defaults = { key: { value: chance.word() } };
+ const { uiSettings } = setup({ esDocSource, defaults });
const result = await uiSettings.getRaw();
- const merged = getDefaultSettings();
- merged.foo = { userValue: 'bar' };
- expect(isEqual(result, merged)).to.equal(true);
- });
- it(`user configuration gets merged into defaults`, async () => {
- const esDocSource = { dateFormat: 'YYYY-MM-DD' };
- const { uiSettings } = setup({ esDocSource });
- const result = await uiSettings.getRaw();
- const merged = getDefaultSettings();
- merged.dateFormat.userValue = 'YYYY-MM-DD';
- expect(isEqual(result, merged)).to.equal(true);
+ expect(result).to.eql({
+ foo: {
+ userValue: 'bar',
+ },
+ key: {
+ value: defaults.key.value,
+ },
+ });
});
});
@@ -276,42 +271,32 @@ describe('ui settings', () => {
assertGetQuery();
});
- it(`returns key value pairs`, async () => {
- const esDocSource = {};
- const { uiSettings } = setup({ esDocSource });
- const result = await uiSettings.getAll();
- const defaults = getDefaultSettings();
- const expectation = {};
- Object.keys(defaults).forEach((key) => {
- expectation[key] = defaults[key].value;
+ it(`returns defaults when es doc is empty`, async () => {
+ const esDocSource = { };
+ const defaults = { foo: { value: 'bar' } };
+ const { uiSettings } = setup({ esDocSource, defaults });
+ expect(await uiSettings.getAll()).to.eql({
+ foo: 'bar'
});
- expect(isEqual(result, expectation)).to.equal(true);
});
- it(`returns key value pairs including user configuration`, async () => {
- const esDocSource = { something: 'user-provided' };
- const { uiSettings } = setup({ esDocSource });
- const result = await uiSettings.getAll();
- const defaults = getDefaultSettings();
- const expectation = {};
- Object.keys(defaults).forEach((key) => {
- expectation[key] = defaults[key].value;
- });
- expectation.something = 'user-provided';
- expect(isEqual(result, expectation)).to.equal(true);
- });
+ it(`merges user values, including ones without defaults, into key value pairs`, async () => {
+ const esDocSource = {
+ foo: 'user-override',
+ bar: 'user-provided',
+ };
- it(`returns key value pairs including user configuration for existing settings`, async () => {
- const esDocSource = { dateFormat: 'YYYY-MM-DD' };
- const { uiSettings } = setup({ esDocSource });
- const result = await uiSettings.getAll();
- const defaults = getDefaultSettings();
- const expectation = {};
- Object.keys(defaults).forEach((key) => {
- expectation[key] = defaults[key].value;
+ const defaults = {
+ foo: {
+ value: 'default'
+ },
+ };
+
+ const { uiSettings } = setup({ esDocSource, defaults });
+ expect(await uiSettings.getAll()).to.eql({
+ foo: 'user-override',
+ bar: 'user-provided',
});
- expectation.dateFormat = 'YYYY-MM-DD';
- expect(isEqual(result, expectation)).to.equal(true);
});
});
@@ -325,9 +310,9 @@ describe('ui settings', () => {
it(`returns the promised value for a key`, async () => {
const esDocSource = {};
- const { uiSettings } = setup({ esDocSource });
+ const defaults = { dateFormat: { value: chance.word() } };
+ const { uiSettings } = setup({ esDocSource, defaults });
const result = await uiSettings.get('dateFormat');
- const defaults = getDefaultSettings();
expect(result).to.equal(defaults.dateFormat.value);
});
@@ -371,23 +356,21 @@ describe('ui settings', () => {
describe('#getAll()', () => {
it('merges intercept value with defaults', async () => {
const { uiSettings } = setup({
+ defaults: {
+ foo: { value: 'foo' },
+ bar: { value: 'bar' },
+ },
+
readInterceptor: () => ({
foo: 'not foo'
}),
});
- const defaults = getDefaultSettings();
- const defaultValues = Object.keys(defaults).reduce((acc, key) => ({
- ...acc,
- [key]: defaults[key].value,
- }), {});
-
expect(await uiSettings.getAll()).to.eql({
- ...defaultValues,
foo: 'not foo',
+ bar: 'bar'
});
});
});
});
-
});
diff --git a/src/ui/ui_settings/ui_exports_consumer.js b/src/ui/ui_settings/ui_exports_consumer.js
new file mode 100644
index 0000000000000..74962c8845049
--- /dev/null
+++ b/src/ui/ui_settings/ui_exports_consumer.js
@@ -0,0 +1,43 @@
+/**
+ * The UiExports class accepts consumer objects that it consults while
+ * trying to consume all of the `uiExport` declarations provided by
+ * plugins.
+ *
+ * UiExportConsumer is instantiated and passed to UiExports, then for
+ * every `uiExport` declaration the `exportConsumer(type)` method is
+ * with the key of the declaration. If this consumer knows how to handle
+ * that key we return a function that will be called with the plugins
+ * and values of all declarations using that key.
+ *
+ * With this, the consumer merges all of the declarations into the
+ * _uiSettingDefaults map, ensuring that there are not collisions along
+ * the way.
+ *
+ * @class UiExportsConsumer
+ */
+export class UiExportsConsumer {
+ _uiSettingDefaults = {};
+
+ exportConsumer(type) {
+ switch (type) {
+ case 'uiSettingDefaults':
+ return (plugin, settingDefinitions) => {
+ Object.keys(settingDefinitions).forEach((key) => {
+ if (key in this._uiSettingDefaults) {
+ throw new Error(`uiSettingDefaults for key "${key}" are already defined`);
+ }
+
+ this._uiSettingDefaults[key] = settingDefinitions[key];
+ });
+ };
+ }
+ }
+
+ /**
+ * Get the map of uiSettingNames to "default" specifications
+ * @return {Object}
+ */
+ getUiSettingDefaults() {
+ return this._uiSettingDefaults;
+ }
+}
diff --git a/src/ui/ui_settings/ui_settings_mixin.js b/src/ui/ui_settings/ui_settings_mixin.js
index 92651ef59e7e5..62b59db991542 100644
--- a/src/ui/ui_settings/ui_settings_mixin.js
+++ b/src/ui/ui_settings/ui_settings_mixin.js
@@ -1,10 +1,15 @@
import { uiSettingsServiceFactory } from './ui_settings_service_factory';
import { getUiSettingsServiceForRequest } from './ui_settings_service_for_request';
import { mirrorStatus } from './mirror_status';
+import { UiExportsConsumer } from './ui_exports_consumer';
export function uiSettingsMixin(kbnServer, server, config) {
const status = kbnServer.status.create('ui settings');
+ // reads the "uiSettingDefaults" from uiExports
+ const uiExportsConsumer = new UiExportsConsumer();
+ kbnServer.uiExports.addConsumer(uiExportsConsumer);
+
if (!config.get('uiSettings.enabled')) {
status.disabled('uiSettings.enabled config is set to `false`');
return;
@@ -17,23 +22,33 @@ export function uiSettingsMixin(kbnServer, server, config) {
// If the ui settings status isn't green we shouldn't be attempting to get
// user settings, since we can't be sure that all the necessary conditions
// (e.g. elasticsearch being available) are met.
- const readUiSettingsInterceptor = () => {
+ const readInterceptor = () => {
if (status.state !== 'green') {
return {};
}
};
+ const getDefaults = () => (
+ uiExportsConsumer.getUiSettingDefaults()
+ );
+
// don't return, just let it happen when the plugins are ready
kbnServer.ready().then(() => {
mirrorStatus(status, kbnServer.status.getForPluginId('elasticsearch'));
});
- server.decorate('server', 'uiSettingsServiceFactory', function (options) {
- return uiSettingsServiceFactory(server, options);
+ server.decorate('server', 'uiSettingsServiceFactory', (options = {}) => {
+ return uiSettingsServiceFactory(server, {
+ getDefaults,
+ ...options
+ });
});
server.decorate('request', 'getUiSettingsService', function () {
- return getUiSettingsServiceForRequest(server, this, readUiSettingsInterceptor);
+ return getUiSettingsServiceForRequest(server, this, {
+ getDefaults,
+ readInterceptor,
+ });
});
server.decorate('server', 'uiSettings', () => {
diff --git a/src/ui/ui_settings/ui_settings_service.js b/src/ui/ui_settings/ui_settings_service.js
index f929d79d91437..57d0db8e9c96b 100644
--- a/src/ui/ui_settings/ui_settings_service.js
+++ b/src/ui/ui_settings/ui_settings_service.js
@@ -1,8 +1,6 @@
import { defaultsDeep, noop } from 'lodash';
import { errors as esErrors } from 'elasticsearch';
-import { getDefaultSettings } from './defaults';
-
function hydrateUserSettings(userSettings) {
return Object.keys(userSettings)
.map(key => ({ key, userValue: userSettings[key] }))
@@ -32,17 +30,21 @@ export class UiSettingsService {
id,
callCluster,
readInterceptor = noop,
+ // we use a function for getDefaults() so that defaults can be different in
+ // different scenarios, and so they can change over time
+ getDefaults = () => ({}),
} = options;
this._callCluster = callCluster;
+ this._getDefaults = getDefaults;
this._readInterceptor = readInterceptor;
this._index = index;
this._type = type;
this._id = id;
}
- getDefaults() {
- return getDefaultSettings();
+ async getDefaults() {
+ return await this._getDefaults();
}
// returns a Promise for the value of the requested setting
@@ -65,7 +67,7 @@ export class UiSettingsService {
async getRaw() {
const userProvided = await this.getUserProvided();
- return defaultsDeep(userProvided, this.getDefaults());
+ return defaultsDeep(userProvided, await this.getDefaults());
}
async getUserProvided(options) {
diff --git a/src/ui/ui_settings/ui_settings_service_factory.js b/src/ui/ui_settings/ui_settings_service_factory.js
index c300bc9bc4bf9..c0b70223a3dda 100644
--- a/src/ui/ui_settings/ui_settings_service_factory.js
+++ b/src/ui/ui_settings/ui_settings_service_factory.js
@@ -8,6 +8,8 @@ import { UiSettingsService } from './ui_settings_service';
* @param {Object} options
* @property {AsyncFunction} options.callCluster function that accepts a method name and
* param object which causes a request via some elasticsearch client
+ * @property {AsyncFunction} [options.getDefaults] async function that returns defaults/details about
+ * the uiSettings.
* @property {AsyncFunction} [options.readInterceptor] async function that is called when the
* UiSettingsService does a read() an has an oportunity to intercept the
* request and return an alternate `_source` value to use.
@@ -18,7 +20,8 @@ export function uiSettingsServiceFactory(server, options) {
const {
callCluster,
- readInterceptor
+ readInterceptor,
+ getDefaults,
} = options;
return new UiSettingsService({
@@ -27,5 +30,6 @@ export function uiSettingsServiceFactory(server, options) {
id: config.get('pkg.version'),
callCluster,
readInterceptor,
+ getDefaults,
});
}
diff --git a/src/ui/ui_settings/ui_settings_service_for_request.js b/src/ui/ui_settings/ui_settings_service_for_request.js
index 650bc98a53781..d43657b6d8f42 100644
--- a/src/ui/ui_settings/ui_settings_service_for_request.js
+++ b/src/ui/ui_settings/ui_settings_service_for_request.js
@@ -2,14 +2,36 @@ import { uiSettingsServiceFactory } from './ui_settings_service_factory';
const BY_REQUEST_CACHE = new WeakMap();
-export function getUiSettingsServiceForRequest(server, request, readInterceptor) {
+/**
+ * Get/create an instance of UiSettingsService bound to a specific request.
+ * Each call is cached (keyed on the request object itself) and subsequent
+ * requests will get the first UiSettingsService instance even if the `options`
+ * have changed.
+ *
+ * @param {Hapi.Server} server
+ * @param {Hapi.Request} request
+ * @param {Object} [options={}]
+ * @property {AsyncFunction} [options.getDefaults] async function that returns defaults/details about
+ * the uiSettings.
+ * @property {AsyncFunction} [options.readInterceptor] async function that is called when the
+ * UiSettingsService does a read() and has an oportunity to intercept the
+ * request and return an alternate `_source` value to use.
+ * @return {UiSettingsService}
+ */
+export function getUiSettingsServiceForRequest(server, request, options = {}) {
if (BY_REQUEST_CACHE.has(request)) {
return BY_REQUEST_CACHE.get(request);
}
+ const {
+ readInterceptor,
+ getDefaults
+ } = options;
+
const adminCluster = server.plugins.elasticsearch.getCluster('admin');
const uiSettingsService = uiSettingsServiceFactory(server, {
readInterceptor,
+ getDefaults,
callCluster(...args) {
return adminCluster.callWithRequest(request, ...args);
}