diff --git a/packages/kbn-interpreter/src/common/index.js b/packages/kbn-interpreter/src/common/index.js index fbf7d9bd0d6f..7205b76839c8 100644 --- a/packages/kbn-interpreter/src/common/index.js +++ b/packages/kbn-interpreter/src/common/index.js @@ -17,8 +17,8 @@ * under the License. */ -export { functionsRegistry } from './lib/functions_registry'; -export { typesRegistry } from './lib/types_registry'; +export { FunctionsRegistry } from './lib/functions_registry'; +export { TypesRegistry } from './lib/types_registry'; export { createError } from './interpreter/create_error'; export { interpretProvider } from './interpreter/interpret'; export { serializeProvider } from './lib/serialize'; diff --git a/packages/kbn-interpreter/src/common/interpreter/interpret.js b/packages/kbn-interpreter/src/common/interpreter/interpret.js index d2a786cd3c85..934f35b856d8 100644 --- a/packages/kbn-interpreter/src/common/interpreter/interpret.js +++ b/packages/kbn-interpreter/src/common/interpreter/interpret.js @@ -22,7 +22,6 @@ import { each, keys, last, mapValues, reduce, zipObject } from 'lodash'; import { getType } from '../lib/get_type'; import { fromExpression } from '../lib/ast'; import { getByAlias } from '../lib/get_by_alias'; -import { typesRegistry } from '../lib/types_registry'; import { castProvider } from './cast'; import { createError } from './create_error'; @@ -103,7 +102,7 @@ export function interpretProvider(config) { } // Validate the function output against the type definition's validate function - const type = typesRegistry.get(fnDef.type); + const type = handlers.types[fnDef.type]; if (type && type.validate) { try { type.validate(fnOutput); diff --git a/packages/kbn-interpreter/src/common/lib/functions_registry.js b/packages/kbn-interpreter/src/common/lib/functions_registry.js index 1c71707d8472..dbf34cf2aa6a 100644 --- a/packages/kbn-interpreter/src/common/lib/functions_registry.js +++ b/packages/kbn-interpreter/src/common/lib/functions_registry.js @@ -20,10 +20,8 @@ import { Registry } from './registry'; import { Fn } from './fn'; -class FunctionsRegistry extends Registry { +export class FunctionsRegistry extends Registry { wrapper(obj) { return new Fn(obj); } } - -export const functionsRegistry = new FunctionsRegistry(); diff --git a/packages/kbn-interpreter/src/common/lib/types_registry.js b/packages/kbn-interpreter/src/common/lib/types_registry.js index 97e28875d7e2..ef4ddffa6318 100644 --- a/packages/kbn-interpreter/src/common/lib/types_registry.js +++ b/packages/kbn-interpreter/src/common/lib/types_registry.js @@ -20,10 +20,8 @@ import { Registry } from './registry'; import { Type } from './type'; -class TypesRegistry extends Registry { +export class TypesRegistry extends Registry { wrapper(obj) { return new Type(obj); } } - -export const typesRegistry = new TypesRegistry(); diff --git a/packages/kbn-interpreter/src/public/browser_registries.js b/packages/kbn-interpreter/src/public/browser_registries.js index 312c934cdede..3fd4b1a866a0 100644 --- a/packages/kbn-interpreter/src/public/browser_registries.js +++ b/packages/kbn-interpreter/src/public/browser_registries.js @@ -19,18 +19,7 @@ import $script from 'scriptjs'; -let resolvePromise = null; -let called = false; - -let populatePromise = new Promise(_resolve => { - resolvePromise = _resolve; -}); - -export const getBrowserRegistries = () => { - return populatePromise; -}; - -const loadBrowserRegistries = (registries, basePath) => { +export const loadBrowserRegistries = (registries, basePath) => { const remainingTypes = Object.keys(registries); const populatedTypes = {}; @@ -56,27 +45,3 @@ const loadBrowserRegistries = (registries, basePath) => { loadType(); }); }; - -export const populateBrowserRegistries = (registries, basePath) => { - if (called) { - const oldPromise = populatePromise; - let newResolve; - populatePromise = new Promise(_resolve => { - newResolve = _resolve; - }); - oldPromise.then(oldTypes => { - loadBrowserRegistries(registries, basePath).then(newTypes => { - newResolve({ - ...oldTypes, - ...newTypes, - }); - }); - }); - return populatePromise; - } - called = true; - loadBrowserRegistries(registries, basePath).then(registries => { - resolvePromise(registries); - }); - return populatePromise; -}; diff --git a/packages/kbn-interpreter/src/public/index.js b/packages/kbn-interpreter/src/public/index.js index de8caad1dbc5..a886c9dd78cd 100644 --- a/packages/kbn-interpreter/src/public/index.js +++ b/packages/kbn-interpreter/src/public/index.js @@ -17,6 +17,6 @@ * under the License. */ -export { populateBrowserRegistries, getBrowserRegistries } from './browser_registries'; +export { loadBrowserRegistries } from './browser_registries'; export { createSocket } from './socket'; -export { initializeInterpreter, interpretAst } from './interpreter'; +export { initializeInterpreter } from './interpreter'; diff --git a/packages/kbn-interpreter/src/public/interpreter.js b/packages/kbn-interpreter/src/public/interpreter.js index ba38df27b6f8..45042ef4002c 100644 --- a/packages/kbn-interpreter/src/public/interpreter.js +++ b/packages/kbn-interpreter/src/public/interpreter.js @@ -19,18 +19,28 @@ import { socketInterpreterProvider } from '../common/interpreter/socket_interpret'; import { serializeProvider } from '../common/lib/serialize'; -import { getSocket } from './socket'; -import { typesRegistry } from '../common/lib/types_registry'; import { createHandlers } from './create_handlers'; -import { functionsRegistry } from '../common/lib/functions_registry'; -import { getBrowserRegistries } from './browser_registries'; -let socket; -let resolve; -const functionList = new Promise(_resolve => (resolve = _resolve)); +export async function initializeInterpreter(socket, typesRegistry, functionsRegistry) { + let resolve; + const functionList = new Promise(_resolve => (resolve = _resolve)); -export async function initializeInterpreter() { - socket = getSocket(); + const getInitializedFunctions = async () => { + return functionList; + }; + + const interpretAst = async (ast, context, handlers) => { + // Load plugins before attempting to get functions, otherwise this gets racey + const serverFunctionList = await functionList; + const interpretFn = await socketInterpreterProvider({ + types: typesRegistry.toJS(), + handlers: { ...handlers, ...createHandlers(socket) }, + functions: functionsRegistry.toJS(), + referableFunctions: serverFunctionList, + socket: socket, + }); + return interpretFn(ast, context); + }; // Listen for interpreter runs socket.on('run', ({ ast, context, id }) => { @@ -42,23 +52,20 @@ export async function initializeInterpreter() { }); // Create the function list - socket.emit('getFunctionList'); - socket.once('functionList', resolve); - return functionList; + let gotFunctionList = false; + socket.once('functionList', (fl) => { + gotFunctionList = true; + resolve(fl); + }); + + const interval = setInterval(() => { + if (gotFunctionList) { + clearInterval(interval); + return; + } + socket.emit('getFunctionList'); + }, 1000); + + return { getInitializedFunctions, interpretAst }; } -// Use the above promise to seed the interpreter with the functions it can defer to -export async function interpretAst(ast, context) { - // Load plugins before attempting to get functions, otherwise this gets racey - return Promise.all([functionList, getBrowserRegistries()]) - .then(([serverFunctionList]) => { - return socketInterpreterProvider({ - types: typesRegistry.toJS(), - handlers: createHandlers(socket), - functions: functionsRegistry.toJS(), - referableFunctions: serverFunctionList, - socket: socket, - }); - }) - .then(interpretFn => interpretFn(ast, context)); -} diff --git a/packages/kbn-interpreter/src/public/socket.js b/packages/kbn-interpreter/src/public/socket.js index e3a2068086b3..7d209e09c688 100644 --- a/packages/kbn-interpreter/src/public/socket.js +++ b/packages/kbn-interpreter/src/public/socket.js @@ -18,22 +18,13 @@ */ import io from 'socket.io-client'; -import { functionsRegistry } from '../common/lib/functions_registry'; -import { getBrowserRegistries } from './browser_registries'; const SOCKET_CONNECTION_TIMEOUT = 5000; // timeout in ms -let socket; -export async function createSocket(basePath) { - if (socket != null) return socket; +export async function createSocket(basePath, functionsRegistry) { - return new Promise((resolve, rej) => { - const reject = p => { - socket = null; // reset the socket on errors - rej(p); - }; - - socket = io({ + return new Promise((resolve, reject) => { + const socket = io({ path: `${basePath}/socket.io`, transports: ['polling', 'websocket'], transportOptions: { @@ -49,12 +40,11 @@ export async function createSocket(basePath) { }); socket.on('getFunctionList', () => { - const pluginsLoaded = getBrowserRegistries(); - pluginsLoaded.then(() => socket.emit('functionList', functionsRegistry.toJS())); + socket.emit('functionList', functionsRegistry.toJS()); }); socket.on('connect', () => { - resolve(); + resolve(socket); socket.off('connectionFailed', errorHandler); socket.off('connect_error', errorHandler); socket.off('connect_timeout', errorHandler); @@ -71,8 +61,3 @@ export async function createSocket(basePath) { socket.on('connect_timeout', errorHandler); }); } - -export function getSocket() { - if (!socket) throw new Error('getSocket failed, socket has not been created'); - return socket; -} diff --git a/packages/kbn-interpreter/src/server/index.js b/packages/kbn-interpreter/src/server/index.js index 3815cad550d0..24d463d668b3 100644 --- a/packages/kbn-interpreter/src/server/index.js +++ b/packages/kbn-interpreter/src/server/index.js @@ -17,6 +17,6 @@ * under the License. */ -export { populateServerRegistries, getServerRegistries } from './server_registries'; +export { populateServerRegistries } from './server_registries'; export { getPluginPaths } from './get_plugin_paths'; export { pluginPaths } from './plugin_paths'; diff --git a/packages/kbn-interpreter/src/server/server_registries.js b/packages/kbn-interpreter/src/server/server_registries.js index 2a456bee7de0..307401cf9a0b 100644 --- a/packages/kbn-interpreter/src/server/server_registries.js +++ b/packages/kbn-interpreter/src/server/server_registries.js @@ -17,55 +17,38 @@ * under the License. */ -import { typesRegistry } from '../common/lib/types_registry'; -import { functionsRegistry as serverFunctions } from '../common/lib/functions_registry'; import { getPluginPaths } from './get_plugin_paths'; -const registries = { - serverFunctions: serverFunctions, - commonFunctions: serverFunctions, - types: typesRegistry, -}; -let resolve = null; -let called = false; +export const populateServerRegistries = registries => { + if (!registries) throw new Error('registries are required'); -const populatePromise = new Promise(_resolve => { - resolve = _resolve; -}); + return new Promise(resolve => { + const remainingTypes = Object.keys(registries); + const populatedTypes = {}; -export const getServerRegistries = () => { - return populatePromise; -}; + const loadType = () => { + const type = remainingTypes.pop(); + getPluginPaths(type).then(paths => { + global.canvas = global.canvas || {}; + global.canvas.register = d => registries[type].register(d); -export const populateServerRegistries = types => { - if (called) { - return populatePromise; - } - called = true; - if (!types || !types.length) throw new Error('types is required'); + paths.forEach(path => { + require(path); // eslint-disable-line import/no-dynamic-require + }); - const remainingTypes = types; - const populatedTypes = {}; + delete global.canvas; - const loadType = () => { - const type = remainingTypes.pop(); - getPluginPaths(type).then(paths => { - global.canvas = global.canvas || {}; - global.canvas.register = d => registries[type].register(d); - - paths.forEach(path => { - require(path); // eslint-disable-line import/no-dynamic-require + populatedTypes[type] = registries[type]; + if (remainingTypes.length) { + loadType(); + } + else { + resolve(populatedTypes); + } }); + }; - delete global.canvas; - - populatedTypes[type] = registries[type]; - if (remainingTypes.length) loadType(); - else resolve(populatedTypes); - }); - }; - - if (remainingTypes.length) loadType(); - return populatePromise; + if (remainingTypes.length) loadType(); + }); }; diff --git a/packages/kbn-interpreter/tasks/build/webpack.config.js b/packages/kbn-interpreter/tasks/build/webpack.config.js index 5d5afc92a249..5f4faea438c0 100644 --- a/packages/kbn-interpreter/tasks/build/webpack.config.js +++ b/packages/kbn-interpreter/tasks/build/webpack.config.js @@ -36,6 +36,7 @@ module.exports = function ({ sourceMaps }, { watch }) { entry: { 'types/all': resolve(PLUGIN_SOURCE_DIR, 'types/register.js'), 'functions/browser/all': resolve(PLUGIN_SOURCE_DIR, 'functions/browser/register.js'), + 'functions/browser/common': resolve(PLUGIN_SOURCE_DIR, 'functions/common/register.js'), }, // there were problems with the node and web targets since this code is actually diff --git a/src/legacy/core_plugins/interpreter/index.js b/src/legacy/core_plugins/interpreter/index.js index 21ab23f1b837..1235b7a471f8 100644 --- a/src/legacy/core_plugins/interpreter/index.js +++ b/src/legacy/core_plugins/interpreter/index.js @@ -25,11 +25,6 @@ export default function (kibana) { id: 'interpreter', require: ['kibana', 'elasticsearch'], publicDir: resolve(__dirname, 'public'), - uiExports: { - hacks: [ - 'plugins/interpreter/load_browser_plugins.js', - ], - }, init, }); } diff --git a/src/legacy/core_plugins/interpreter/init.js b/src/legacy/core_plugins/interpreter/init.js index 74d07d60b480..1d7a994a45ad 100644 --- a/src/legacy/core_plugins/interpreter/init.js +++ b/src/legacy/core_plugins/interpreter/init.js @@ -18,10 +18,16 @@ */ import { routes } from './server/routes'; -import { functionsRegistry } from '@kbn/interpreter/common'; +import { FunctionsRegistry, TypesRegistry } from '@kbn/interpreter/common'; import { populateServerRegistries } from '@kbn/interpreter/server'; export default async function (server /*options*/) { + + const registries = { + serverFunctions: new FunctionsRegistry(), + types: new TypesRegistry() + }; + server.injectUiAppVars('canvas', () => { const config = server.config(); const basePath = config.get('server.basePath'); @@ -35,12 +41,14 @@ export default async function (server /*options*/) { kbnIndex: config.get('kibana.index'), esShardTimeout: config.get('elasticsearch.shardTimeout'), esApiVersion: config.get('elasticsearch.apiVersion'), - serverFunctions: functionsRegistry.toArray(), + serverFunctions: registries.serverFunctions.toArray(), basePath, reportingBrowserType, }; }); - await populateServerRegistries(['serverFunctions', 'types']); + await populateServerRegistries(registries); + + server.expose(registries); routes(server); } diff --git a/src/legacy/core_plugins/interpreter/public/load_browser_plugins.js b/src/legacy/core_plugins/interpreter/public/functions_registry.js similarity index 71% rename from src/legacy/core_plugins/interpreter/public/load_browser_plugins.js rename to src/legacy/core_plugins/interpreter/public/functions_registry.js index a8c43ceaaebb..410095d9c19f 100644 --- a/src/legacy/core_plugins/interpreter/public/load_browser_plugins.js +++ b/src/legacy/core_plugins/interpreter/public/functions_registry.js @@ -17,13 +17,7 @@ * under the License. */ -import chrome from 'ui/chrome'; -import { populateBrowserRegistries } from '@kbn/interpreter/public'; -import { typesRegistry, functionsRegistry } from '@kbn/interpreter/common'; -const types = { - browserFunctions: functionsRegistry, - types: typesRegistry -}; +import { FunctionsRegistry } from '@kbn/interpreter/common'; -populateBrowserRegistries(types, chrome.getBasePath()); +export const functionsRegistry = new FunctionsRegistry(); diff --git a/src/legacy/core_plugins/interpreter/public/interpreter.js b/src/legacy/core_plugins/interpreter/public/interpreter.js new file mode 100644 index 000000000000..f31e29c58ce3 --- /dev/null +++ b/src/legacy/core_plugins/interpreter/public/interpreter.js @@ -0,0 +1,60 @@ +/* + * 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 { initializeInterpreter, loadBrowserRegistries, createSocket } from '@kbn/interpreter/public'; +import chrome from 'ui/chrome'; +import { functionsRegistry } from './functions_registry'; +import { typesRegistry } from './types_registry'; + +const basePath = chrome.getBasePath(); + +const types = { + browserFunctions: functionsRegistry, + types: typesRegistry +}; + +let _resolve; +let _interpreterPromise; + +const initialize = async () => { + await loadBrowserRegistries(types, basePath); + const socket = await createSocket(basePath, functionsRegistry); + initializeInterpreter(socket, typesRegistry, functionsRegistry).then(interpreter => { + _resolve({ interpreter, socket }); + }); +}; + +export const getInterpreter = async () => { + if (!_interpreterPromise) { + _interpreterPromise = new Promise(resolve => _resolve = resolve); + initialize(); + } + return await _interpreterPromise; +}; + +export const interpretAst = async (...params) => { + const { interpreter } = await getInterpreter(); + return await interpreter.interpretAst(...params); +}; + +export const updateInterpreterFunctions = async () => { + const { socket } = await getInterpreter(); + socket.emit('updateFunctionList'); +}; diff --git a/src/legacy/core_plugins/interpreter/public/types_registry.js b/src/legacy/core_plugins/interpreter/public/types_registry.js new file mode 100644 index 000000000000..10eada72e2c1 --- /dev/null +++ b/src/legacy/core_plugins/interpreter/public/types_registry.js @@ -0,0 +1,23 @@ +/* + * 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 { TypesRegistry } from '@kbn/interpreter/common'; + +export const typesRegistry = new TypesRegistry(); diff --git a/src/legacy/core_plugins/interpreter/server/lib/route_expression/browser.js b/src/legacy/core_plugins/interpreter/server/lib/route_expression/browser.js index 0fe27f4d27c6..4b3d43ef9aca 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/route_expression/browser.js +++ b/src/legacy/core_plugins/interpreter/server/lib/route_expression/browser.js @@ -22,36 +22,46 @@ import uuid from 'uuid/v4'; export const browser = ({ socket, serialize, deserialize }) => { // Note that we need to be careful about how many times routeExpressionProvider is called, because of the socket.once below. // It's too bad we can't get a list of browser plugins on the server - const getClientFunctions = new Promise(resolve => { - socket.emit('getFunctionList'); - socket.once('functionList', resolve); + + let getFunctionsPromise; + socket.on('updateFunctionList', () => { + getFunctionsPromise = undefined; }); - return getClientFunctions.then(functions => { - return { - interpret: (ast, context) => { - return new Promise((resolve, reject) => { - const id = uuid(); - const listener = resp => { - if (resp.type === 'msgError') { - const { value } = resp; - // cast error strings back into error instances - const err = value instanceof Error ? value : new Error(value); - if (value.stack) err.stack = value.stack; - // Reject's with a legit error. Check! Environments should always reject with an error when something bad happens - reject(err); - } else { - resolve(deserialize(resp.value)); - } - }; + const getFunctions = async () => { + if (!getFunctionsPromise) { + getFunctionsPromise = new Promise(resolve => { + socket.once('functionList', resolve); + socket.emit('getFunctionList'); + }); + } - // {type: msgSuccess or msgError, value: foo}. Doesn't matter if it's success or error, we do the same thing for now - socket.once(`resp:${id}`, listener); + return Object.keys(await getFunctionsPromise); + }; - socket.emit('run', { ast, context: serialize(context), id }); - }); - }, - getFunctions: () => Object.keys(functions), - }; - }); + return { + interpret: (ast, context) => { + return new Promise(async (resolve, reject) => { + await getFunctions(); + const id = uuid(); + const listener = resp => { + if (resp.type === 'msgError') { + const { value } = resp; + // cast error strings back into error instances + const err = value instanceof Error ? value : new Error(value); + if (value.stack) err.stack = value.stack; + // Reject's with a legit error. Check! Environments should always reject with an error when something bad happens + reject(err); + } else { + resolve(deserialize(resp.value)); + } + }; + + // {type: msgSuccess or msgError, value: foo}. Doesn't matter if it's success or error, we do the same thing for now + socket.once(`resp:${id}`, listener); + + socket.emit('run', { ast, context: serialize(context), id }); + }); + }, getFunctions + }; }; diff --git a/src/legacy/core_plugins/interpreter/server/lib/route_expression/index.js b/src/legacy/core_plugins/interpreter/server/lib/route_expression/index.js index cd56b7e7bfe7..7098572ce2b4 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/route_expression/index.js +++ b/src/legacy/core_plugins/interpreter/server/lib/route_expression/index.js @@ -23,8 +23,8 @@ export const routeExpressionProvider = environments => { async function routeExpression(ast, context = null) { // List of environments in order of preference - return Promise.all(environments).then(environments => { - const environmentFunctions = environments.map(env => env.getFunctions()); + return Promise.all(environments).then(async environments => { + const environmentFunctions = await Promise.all(environments.map(env => env.getFunctions())); // Grab name of the first function in the chain const fnName = ast.chain[0].function.toLowerCase(); diff --git a/src/legacy/core_plugins/interpreter/server/lib/route_expression/server.js b/src/legacy/core_plugins/interpreter/server/lib/route_expression/server.js index 23fe1487ddcc..663e84235578 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/route_expression/server.js +++ b/src/legacy/core_plugins/interpreter/server/lib/route_expression/server.js @@ -17,12 +17,11 @@ * under the License. */ -import { getServerRegistries } from '@kbn/interpreter/server'; import { interpretProvider } from '@kbn/interpreter/common'; import { createHandlers } from '../create_handlers'; export const server = async ({ onFunctionNotFound, server, request }) => { - const { serverFunctions, types } = await getServerRegistries(['serverFunctions', 'types']); + const { serverFunctions, types } = server.plugins.interpreter; return { interpret: (ast, context) => { diff --git a/src/legacy/core_plugins/interpreter/server/lib/route_expression/thread/worker.js b/src/legacy/core_plugins/interpreter/server/lib/route_expression/thread/worker.js index e26e3052aedc..cef00153e0fc 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/route_expression/thread/worker.js +++ b/src/legacy/core_plugins/interpreter/server/lib/route_expression/thread/worker.js @@ -19,10 +19,15 @@ import uuid from 'uuid/v4'; import { populateServerRegistries } from '@kbn/interpreter/server'; -import { interpretProvider, serializeProvider } from '@kbn/interpreter/common'; +import { interpretProvider, serializeProvider, FunctionsRegistry, TypesRegistry } from '@kbn/interpreter/common'; // We actually DO need populateServerRegistries here since this is a different node process -const pluginsReady = populateServerRegistries(['commonFunctions', 'types']); +const registries = { + commonFunctions: new FunctionsRegistry(), + types: new TypesRegistry(), +}; + +const pluginsReady = populateServerRegistries(registries); const heap = {}; process.on('message', msg => { diff --git a/src/legacy/core_plugins/interpreter/server/routes/socket.js b/src/legacy/core_plugins/interpreter/server/routes/socket.js index 8befd511937e..6201eaf70ca8 100644 --- a/src/legacy/core_plugins/interpreter/server/routes/socket.js +++ b/src/legacy/core_plugins/interpreter/server/routes/socket.js @@ -18,8 +18,7 @@ */ import socket from 'socket.io'; -import { serializeProvider, typesRegistry } from '@kbn/interpreter/common'; -import { getServerRegistries } from '@kbn/interpreter/server'; +import { serializeProvider } from '@kbn/interpreter/common'; import { routeExpressionProvider } from '../lib/route_expression/index'; import { browser } from '../lib/route_expression/browser'; import { thread } from '../lib/route_expression/thread/index'; @@ -54,7 +53,7 @@ export function socketApi(server) { const request = await getModifiedRequest(server, socket); if (!request) return; // do nothing without the request object - const types = typesRegistry.toJS(); + const types = server.plugins.interpreter.types.toJS(); const { serialize, deserialize } = serializeProvider(types); // I'd love to find a way to generalize all of these, but they each need a different set of things @@ -70,9 +69,7 @@ export function socketApi(server) { } socket.on('getFunctionList', () => { - getServerRegistries().then(({ serverFunctions }) => - socket.emit('functionList', serverFunctions.toJS()) - ); + socket.emit('functionList', server.plugins.interpreter.serverFunctions.toJS()); }); socket.on('run', async ({ ast, context, id }) => { diff --git a/x-pack/plugins/canvas/index.js b/x-pack/plugins/canvas/index.js index ed3e8557d403..030d43684eca 100644 --- a/x-pack/plugins/canvas/index.js +++ b/x-pack/plugins/canvas/index.js @@ -14,7 +14,7 @@ export function canvas(kibana) { return new kibana.Plugin({ id: CANVAS_APP, configPrefix: 'xpack.canvas', - require: ['kibana', 'elasticsearch', 'xpack_main'], + require: ['kibana', 'elasticsearch', 'xpack_main', 'interpreter'], publicDir: resolve(__dirname, 'public'), uiExports: { app: { diff --git a/x-pack/plugins/canvas/init.js b/x-pack/plugins/canvas/init.js index d91c7e8a70e5..e04197670928 100644 --- a/x-pack/plugins/canvas/init.js +++ b/x-pack/plugins/canvas/init.js @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionsRegistry } from '@kbn/interpreter/common'; -import { populateServerRegistries } from '@kbn/interpreter/server'; import { routes } from './server/routes'; import { commonFunctions } from './common/functions'; import { registerCanvasUsageCollector } from './server/usage'; import { loadSampleData } from './server/sample_data'; export default async function(server /*options*/) { + const functionsRegistry = server.plugins.interpreter.serverFunctions; + server.injectUiAppVars('canvas', async () => { const config = server.config(); const basePath = config.get('server.basePath'); @@ -40,8 +40,5 @@ export default async function(server /*options*/) { registerCanvasUsageCollector(server); loadSampleData(server); - - // Do not initialize the app until the registries are populated - await populateServerRegistries(['serverFunctions', 'types']); routes(server); } diff --git a/x-pack/plugins/canvas/public/components/app/index.js b/x-pack/plugins/canvas/public/components/app/index.js index ad9cf615dd1c..688696bc8586 100644 --- a/x-pack/plugins/canvas/public/components/app/index.js +++ b/x-pack/plugins/canvas/public/components/app/index.js @@ -4,11 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - createSocket, - initializeInterpreter, - populateBrowserRegistries, -} from '@kbn/interpreter/public'; +import { functionsRegistry } from 'plugins/interpreter/functions_registry'; +import { getInterpreter, updateInterpreterFunctions } from 'plugins/interpreter/interpreter'; +import { loadBrowserRegistries } from '@kbn/interpreter/public'; import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; import { getAppReady, getBasePath } from '../../state/selectors/app'; @@ -54,11 +52,12 @@ const mapDispatchToProps = dispatch => ({ // TODO: the correct socket path should come from upstream, using the constant here is not ideal setAppReady: basePath => async () => { try { + // wait for core interpreter to load + await getInterpreter(); // initialize the socket and interpreter - await createSocket(basePath); - loadPrivateBrowserFunctions(); - await populateBrowserRegistries(types, basePath); - await initializeInterpreter(); + loadPrivateBrowserFunctions(functionsRegistry); + await updateInterpreterFunctions(); + await loadBrowserRegistries(types, basePath); // set app state to ready dispatch(appReady()); diff --git a/x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js b/x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js index 7cb5a6f3c54f..0e696aafbe5b 100644 --- a/x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js +++ b/x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { interpretAst } from '@kbn/interpreter/public'; +import { interpretAst } from 'plugins/interpreter/interpreter'; import { pure, compose, lifecycle, withState, branch, renderComponent } from 'recompose'; import { PropTypes } from 'prop-types'; import { Loading } from '../../loading'; diff --git a/x-pack/plugins/canvas/public/components/function_form_list/index.js b/x-pack/plugins/canvas/public/components/function_form_list/index.js index 00046c65c947..feea4b2f1b7c 100644 --- a/x-pack/plugins/canvas/public/components/function_form_list/index.js +++ b/x-pack/plugins/canvas/public/components/function_form_list/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { interpretAst } from '@kbn/interpreter/public'; +import { interpretAst } from 'plugins/interpreter/interpreter'; import { compose, withProps } from 'recompose'; import { get } from 'lodash'; import { toExpression } from '@kbn/interpreter/common'; diff --git a/x-pack/plugins/canvas/public/functions/filters.js b/x-pack/plugins/canvas/public/functions/filters.js index ca78b119d2a5..5871366c1c0d 100644 --- a/x-pack/plugins/canvas/public/functions/filters.js +++ b/x-pack/plugins/canvas/public/functions/filters.js @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { interpretAst } from '@kbn/interpreter/public'; -import { fromExpression, typesRegistry } from '@kbn/interpreter/common'; +import { interpretAst } from 'plugins/interpreter/interpreter'; +import { typesRegistry } from 'plugins/interpreter/types_registry'; +import { fromExpression } from '@kbn/interpreter/common'; import { getState } from '../state/store'; import { getGlobalFilterExpression } from '../state/selectors/workpad'; diff --git a/x-pack/plugins/canvas/public/lib/function_definitions.js b/x-pack/plugins/canvas/public/lib/function_definitions.js index 40b122f2f6a0..ec40105f72e3 100644 --- a/x-pack/plugins/canvas/public/lib/function_definitions.js +++ b/x-pack/plugins/canvas/public/lib/function_definitions.js @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { functionsRegistry } from 'plugins/interpreter/functions_registry'; import uniqBy from 'lodash.uniqby'; -import { getBrowserRegistries } from '@kbn/interpreter/public'; import { getServerFunctions } from '../state/selectors/app'; export async function getFunctionDefinitions(state) { - const { browserFunctions } = await getBrowserRegistries(); const serverFunctions = getServerFunctions(state); - return uniqBy(serverFunctions.concat(browserFunctions.toArray()), 'name'); + return uniqBy(serverFunctions.concat(functionsRegistry.toArray()), 'name'); } diff --git a/x-pack/plugins/canvas/public/lib/functions_registry.js b/x-pack/plugins/canvas/public/lib/functions_registry.js deleted file mode 100644 index f90fe453e9a1..000000000000 --- a/x-pack/plugins/canvas/public/lib/functions_registry.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// export the common registry here, so it's available in plugin public code -export { functionsRegistry } from '@kbn/interpreter/common'; diff --git a/x-pack/plugins/canvas/public/lib/load_private_browser_functions.js b/x-pack/plugins/canvas/public/lib/load_private_browser_functions.js index 85b995c026a1..ce57ffd33e8b 100644 --- a/x-pack/plugins/canvas/public/lib/load_private_browser_functions.js +++ b/x-pack/plugins/canvas/public/lib/load_private_browser_functions.js @@ -6,7 +6,6 @@ import { commonFunctions } from '../../common/functions'; import { clientFunctions } from '../functions'; -import { functionsRegistry } from './functions_registry'; /* Functions loaded here use PRIVATE APIs @@ -15,11 +14,11 @@ import { functionsRegistry } from './functions_registry'; few of these things as we can't thread them. */ -function addFunction(fnDef) { - functionsRegistry.register(fnDef); -} +export const loadPrivateBrowserFunctions = functionsRegistry => { + function addFunction(fnDef) { + functionsRegistry.register(fnDef); + } -export const loadPrivateBrowserFunctions = () => { clientFunctions.forEach(addFunction); commonFunctions.forEach(addFunction); }; diff --git a/x-pack/plugins/canvas/public/lib/run_interpreter.js b/x-pack/plugins/canvas/public/lib/run_interpreter.js index f9a890b77f14..d3f4de306778 100644 --- a/x-pack/plugins/canvas/public/lib/run_interpreter.js +++ b/x-pack/plugins/canvas/public/lib/run_interpreter.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { interpretAst } from '@kbn/interpreter/public'; +import { interpretAst } from 'plugins/interpreter/interpreter'; import { fromExpression, getType } from '@kbn/interpreter/common'; import { notify } from './notify'; diff --git a/x-pack/plugins/canvas/public/lib/types_registry.js b/x-pack/plugins/canvas/public/lib/types_registry.js deleted file mode 100644 index 292e1547f482..000000000000 --- a/x-pack/plugins/canvas/public/lib/types_registry.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// export the common registry here, so it's available in plugin public code -export { typesRegistry } from '@kbn/interpreter/common'; diff --git a/x-pack/plugins/canvas/public/state/actions/elements.js b/x-pack/plugins/canvas/public/state/actions/elements.js index f6a4a16db743..55fb48fd8f02 100644 --- a/x-pack/plugins/canvas/public/state/actions/elements.js +++ b/x-pack/plugins/canvas/public/state/actions/elements.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { interpretAst } from '@kbn/interpreter/public'; +import { interpretAst } from 'plugins/interpreter/interpreter'; import { createAction } from 'redux-actions'; import { createThunk } from 'redux-thunks'; import { set, del } from 'object-path-immutable'; diff --git a/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js b/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js index e2385c87b546..341112e55335 100644 --- a/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js +++ b/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js @@ -28,6 +28,7 @@ export function getWebpackConfig({ devtool, watch } = {}) { 'uis/datasources/all': path.join(sourceDir, 'uis/datasources/register.js'), 'uis/arguments/all': path.join(sourceDir, 'uis/arguments/register.js'), 'functions/browser/all': path.join(sourceDir, 'functions/browser/register.js'), + 'functions/browser/common': path.join(sourceDir, 'functions/common/register.js'), 'templates/all': path.join(sourceDir, 'templates/register.js'), 'uis/tags/all': path.join(sourceDir, 'uis/tags/register.js'), },