diff --git a/.eslintignore b/.eslintignore index f697ad004caab..50901af5b9eea 100644 --- a/.eslintignore +++ b/.eslintignore @@ -27,7 +27,8 @@ bower_components /x-pack/coverage /x-pack/build /x-pack/plugins/**/__tests__/fixtures/** -/x-pack/plugins/canvas/common/lib/grammar.js +/packages/kbn-interpreter/common/lib/grammar.js +/packages/kbn-interpreter/plugin /x-pack/plugins/canvas/canvas_plugin /x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts **/*.js.snap diff --git a/package.json b/package.json index b0555fad091e1..d4f63df304f9a 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "@kbn/pm": "1.0.0", "@kbn/test-subj-selector": "0.2.1", "@kbn/ui-framework": "1.0.0", + "@kbn/interpreter": "1.0.0", "JSONStream": "1.1.1", "abortcontroller-polyfill": "^1.1.9", "angular": "1.6.9", @@ -383,4 +384,4 @@ "node": "8.11.4", "yarn": "^1.10.1" } -} \ No newline at end of file +} diff --git a/packages/kbn-interpreter/.babelrc b/packages/kbn-interpreter/.babelrc new file mode 100644 index 0000000000000..dc6a77bbe0bcd --- /dev/null +++ b/packages/kbn-interpreter/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@kbn/babel-preset/webpack_preset"] +} diff --git a/x-pack/plugins/canvas/common/interpreter/cast.js b/packages/kbn-interpreter/common/interpreter/cast.js similarity index 53% rename from x-pack/plugins/canvas/common/interpreter/cast.js rename to packages/kbn-interpreter/common/interpreter/cast.js index 7e559afcba40e..cc257a7dc55e0 100644 --- a/x-pack/plugins/canvas/common/interpreter/cast.js +++ b/packages/kbn-interpreter/common/interpreter/cast.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 { getType } from '../lib/get_type'; @@ -19,8 +32,9 @@ export function castProvider(types) { for (let i = 0; i < toTypeNames.length; i++) { // First check if the current type can cast to this type - if (fromTypeDef && fromTypeDef.castsTo(toTypeNames[i])) + if (fromTypeDef && fromTypeDef.castsTo(toTypeNames[i])) { return fromTypeDef.to(node, toTypeNames[i], types); + } // If that isn't possible, check if this type can cast from the current type const toTypeDef = types[toTypeNames[i]]; diff --git a/packages/kbn-interpreter/common/interpreter/create_error.js b/packages/kbn-interpreter/common/interpreter/create_error.js new file mode 100644 index 0000000000000..2740358b1c960 --- /dev/null +++ b/packages/kbn-interpreter/common/interpreter/create_error.js @@ -0,0 +1,26 @@ +/* + * 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. + */ + +export const createError = err => ({ + type: 'error', + error: { + stack: process.env.NODE_ENV === 'production' ? undefined : err.stack, + message: typeof err === 'string' ? err : err.message, + }, +}); diff --git a/x-pack/plugins/canvas/common/interpreter/interpret.js b/packages/kbn-interpreter/common/interpreter/interpret.js similarity index 88% rename from x-pack/plugins/canvas/common/interpreter/interpret.js rename to packages/kbn-interpreter/common/interpreter/interpret.js index ff7a2547f236f..d2a786cd3c85d 100644 --- a/x-pack/plugins/canvas/common/interpreter/interpret.js +++ b/packages/kbn-interpreter/common/interpreter/interpret.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 clone from 'lodash.clone'; @@ -112,8 +125,9 @@ export function interpretProvider(config) { (argAsts, argAst, argName) => { const argDef = getByAlias(argDefs, argName); // TODO: Implement a system to allow for undeclared arguments - if (!argDef) + if (!argDef) { throw new Error(`Unknown argument '${argName}' passed to function '${fnDef.name}'`); + } argAsts[argDef.name] = (argAsts[argDef.name] || []).concat(argAst); return argAsts; @@ -142,8 +156,9 @@ export function interpretProvider(config) { const argAstsWithDefaults = reduce( argDefs, (argAsts, argDef, argName) => { - if (typeof argAsts[argName] === 'undefined' && typeof argDef.default !== 'undefined') + if (typeof argAsts[argName] === 'undefined' && typeof argDef.default !== 'undefined') { argAsts[argName] = [fromExpression(argDef.default, 'argument')]; + } return argAsts; }, diff --git a/x-pack/plugins/canvas/common/interpreter/socket_interpret.js b/packages/kbn-interpreter/common/interpreter/socket_interpret.js similarity index 72% rename from x-pack/plugins/canvas/common/interpreter/socket_interpret.js rename to packages/kbn-interpreter/common/interpreter/socket_interpret.js index c8d5acf4fdd52..1ea95e0f5f6f1 100644 --- a/x-pack/plugins/canvas/common/interpreter/socket_interpret.js +++ b/packages/kbn-interpreter/common/interpreter/socket_interpret.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 uuid from 'uuid/v4'; @@ -40,8 +53,9 @@ export function socketInterpreterProvider({ // Get the list of functions that are known elsewhere return Promise.resolve(referableFunctions).then(referableFunctionMap => { // Check if the not-found function is in the list of alternatives, if not, throw - if (!getByAlias(referableFunctionMap, functionName)) + if (!getByAlias(referableFunctionMap, functionName)) { throw new Error(`Function not found: ${functionName}`); + } // set a unique message ID so the code knows what response to process const id = uuid(); diff --git a/packages/kbn-interpreter/common/lib/arg.js b/packages/kbn-interpreter/common/lib/arg.js new file mode 100644 index 0000000000000..0aa2b52e35acb --- /dev/null +++ b/packages/kbn-interpreter/common/lib/arg.js @@ -0,0 +1,37 @@ +/* + * 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 { includes } from 'lodash'; + +export function Arg(config) { + if (config.name === '_') throw Error('Arg names must not be _. Use it in aliases instead.'); + this.name = config.name; + this.required = config.required || false; + this.help = config.help || ''; + this.types = config.types || []; + this.default = config.default; + this.aliases = config.aliases || []; + this.multi = config.multi == null ? false : config.multi; + this.resolve = config.resolve == null ? true : config.resolve; + this.options = config.options || []; + this.accepts = type => { + if (!this.types.length) return true; + return includes(config.types, type); + }; +} diff --git a/packages/kbn-interpreter/common/lib/arg.test.js b/packages/kbn-interpreter/common/lib/arg.test.js new file mode 100644 index 0000000000000..2edd65cd4af49 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/arg.test.js @@ -0,0 +1,35 @@ +/* + * 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 { Arg } from './arg'; + +describe('Arg', () => { + it('sets required to false by default', () => { + const isOptional = new Arg({ + name: 'optional_me', + }); + expect(isOptional.required).toBe(false); + + const isRequired = new Arg({ + name: 'require_me', + required: true, + }); + expect(isRequired.required).toBe(true); + }); +}); diff --git a/x-pack/plugins/canvas/common/lib/__tests__/ast.from_expression.js b/packages/kbn-interpreter/common/lib/ast.from_expression.test.js similarity index 59% rename from x-pack/plugins/canvas/common/lib/__tests__/ast.from_expression.js rename to packages/kbn-interpreter/common/lib/ast.from_expression.test.js index 631973247dc6c..c144770f94c54 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/ast.from_expression.js +++ b/packages/kbn-interpreter/common/lib/ast.from_expression.test.js @@ -1,35 +1,47 @@ /* - * 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. + * 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 expect from 'expect.js'; -import { fromExpression } from '../ast'; -import { getType } from '../../lib/get_type'; +import { fromExpression } from './ast'; +import { getType } from './get_type'; describe('ast fromExpression', () => { describe('invalid expression', () => { it('throws when empty', () => { const check = () => fromExpression(''); - expect(check).to.throwException(/Unable to parse expression/i); + expect(check).toThrowError(/Unable to parse expression/i); }); it('throws with invalid expression', () => { const check = () => fromExpression('wat!'); - expect(check).to.throwException(/Unable to parse expression/i); + expect(check).toThrowError(/Unable to parse expression/i); }); }); describe('single item expression', () => { it('is a chain', () => { const expression = 'whatever'; - expect(fromExpression(expression)).to.have.property('chain'); + expect(fromExpression(expression)).toHaveProperty('chain'); }); it('is a value', () => { const expression = '"hello"'; - expect(fromExpression(expression, 'argument')).to.equal('hello'); + expect(fromExpression(expression, 'argument')).toBe('hello'); }); describe('function without arguments', () => { @@ -44,15 +56,15 @@ describe('ast fromExpression', () => { }); it('is a function ', () => { - expect(getType(block)).to.equal('function'); + expect(getType(block)).toBe('function'); }); it('is csv function', () => { - expect(block.function).to.equal('csv'); + expect(block.function).toBe('csv'); }); it('has no arguments', () => { - expect(block.arguments).to.eql({}); + expect(block.arguments).toEqual({}); }); }); @@ -68,17 +80,17 @@ describe('ast fromExpression', () => { }); it('has arguemnts properties', () => { - expect(block.arguments).not.to.eql({}); + expect(block.arguments).not.toEqual({}); }); it('has index argument with string value', () => { - expect(block.arguments).to.have.property('index'); - expect(block.arguments.index).to.eql(['logstash-*']); + expect(block.arguments).toHaveProperty('index'); + expect(block.arguments.index).toEqual(['logstash-*']); }); it('has oranges argument with string value', () => { - expect(block.arguments).to.have.property('oranges'); - expect(block.arguments.oranges).to.eql(['bananas']); + expect(block.arguments).toHaveProperty('oranges'); + expect(block.arguments.oranges).toEqual(['bananas']); }); }); @@ -94,12 +106,12 @@ describe('ast fromExpression', () => { }); it('is expression type', () => { - expect(block.arguments).to.have.property('exampleFunction'); - expect(block.arguments.exampleFunction[0]).to.have.property('type', 'expression'); + expect(block.arguments).toHaveProperty('exampleFunction'); + expect(block.arguments.exampleFunction[0]).toHaveProperty('type'); }); it('has expected shape', () => { - expect(block.arguments.exampleFunction).to.eql([ + expect(block.arguments.exampleFunction).toEqual([ { type: 'expression', chain: [ @@ -128,12 +140,12 @@ describe('ast fromExpression', () => { }); it('is expression type', () => { - expect(block.arguments).to.have.property('examplePartial'); - expect(block.arguments.examplePartial[0]).to.have.property('type', 'expression'); + expect(block.arguments).toHaveProperty('examplePartial'); + expect(block.arguments.examplePartial[0]).toHaveProperty('type'); }); it('has expected shape', () => { - expect(block.arguments.examplePartial).to.eql([ + expect(block.arguments.examplePartial).toEqual([ { type: 'expression', chain: [ diff --git a/x-pack/plugins/canvas/common/lib/ast.js b/packages/kbn-interpreter/common/lib/ast.js similarity index 81% rename from x-pack/plugins/canvas/common/lib/ast.js rename to packages/kbn-interpreter/common/lib/ast.js index b31848944e9db..61cfe94ac955c 100644 --- a/x-pack/plugins/canvas/common/lib/ast.js +++ b/packages/kbn-interpreter/common/lib/ast.js @@ -1,10 +1,23 @@ /* - * 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. + * 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 { getType } from '../lib/get_type'; +import { getType } from './get_type'; import { parse } from './grammar'; function getArgumentString(arg, argKey, level = 0) { @@ -48,8 +61,9 @@ function getExpressionArgs(block, level = 0) { const lineLength = acc.split('\n').pop().length; // if arg values are too long, move it to the next line - if (level === 0 && lineLength + argString.length > MAX_LINE_LENGTH) + if (level === 0 && lineLength + argString.length > MAX_LINE_LENGTH) { return `${acc}\n ${argString}`; + } // append arg values to existing arg values if (lineLength > 0) return `${acc} ${argString}`; diff --git a/x-pack/plugins/canvas/common/lib/__tests__/ast.to_expression.js b/packages/kbn-interpreter/common/lib/ast.to_expression.test.js similarity index 83% rename from x-pack/plugins/canvas/common/lib/__tests__/ast.to_expression.js rename to packages/kbn-interpreter/common/lib/ast.to_expression.test.js index 4b5985832e6ab..455b12f583f30 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/ast.to_expression.js +++ b/packages/kbn-interpreter/common/lib/ast.to_expression.test.js @@ -1,18 +1,39 @@ /* - * 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. + * 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 expect from 'expect.js'; -import { toExpression } from '../ast'; +import { toExpression } from './ast'; describe('ast toExpression', () => { describe('single expression', () => { + it('throws if no type included', () => { + const errMsg = 'Objects must have a type property'; + const astObject = { hello: 'world' }; + expect(() => toExpression(astObject)).toThrowError(errMsg); + }); + it('throws if not correct type', () => { const errMsg = 'Expression must be an expression or argument function'; - const astObject = { hello: 'world' }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + const astObject = { + type: 'hi', + hello: 'world', + }; + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('throws if expression without chain', () => { @@ -21,7 +42,7 @@ describe('ast toExpression', () => { type: 'expression', hello: 'world', }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('throws if arguments type is invalid', () => { @@ -29,7 +50,7 @@ describe('ast toExpression', () => { const invalidTypes = [null, []]; function validate(obj) { - expect(() => toExpression(obj)).to.throwException(errMsg); + expect(() => toExpression(obj)).toThrowError(errMsg); } for (let i = 0; i < invalidTypes.length; i++) { @@ -56,12 +77,12 @@ describe('ast toExpression', () => { function: 'pointseries', arguments: null, }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('throws on invalid argument type', () => { const argType = '__invalid__wat__'; - const errMsg = `invalid argument type: ${argType}`; + const errMsg = `Invalid argument type in AST: ${argType}`; const astObject = { type: 'expression', chain: [ @@ -80,7 +101,7 @@ describe('ast toExpression', () => { ], }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('throws on expressions without chains', () => { @@ -104,7 +125,7 @@ describe('ast toExpression', () => { ], }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('throws on nameless functions and partials', () => { @@ -120,7 +141,7 @@ describe('ast toExpression', () => { ], }; - expect(() => toExpression(astObject)).to.throwException(errMsg); + expect(() => toExpression(astObject)).toThrowError(errMsg); }); it('single expression', () => { @@ -136,7 +157,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv'); + expect(expression).toBe('csv'); }); it('single expression with string argument', () => { @@ -154,7 +175,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv input="stuff\nthings"'); + expect(expression).toBe('csv input="stuff\nthings"'); }); it('single expression string value with a backslash', () => { @@ -172,7 +193,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv input="slash \\\\\\\\ slash"'); + expect(expression).toBe('csv input="slash \\\\\\\\ slash"'); }); it('single expression string value with a double quote', () => { @@ -190,7 +211,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv input="stuff\nthings\n\\"such\\""'); + expect(expression).toBe('csv input="stuff\nthings\n\\"such\\""'); }); it('single expression with number argument', () => { @@ -208,7 +229,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('series input=1234'); + expect(expression).toBe('series input=1234'); }); it('single expression with boolean argument', () => { @@ -226,7 +247,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('series input=true'); + expect(expression).toBe('series input=true'); }); it('single expression with null argument', () => { @@ -244,7 +265,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('series input=null'); + expect(expression).toBe('series input=null'); }); it('single expression with multiple arguments', () => { @@ -263,7 +284,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv input="stuff\nthings" separator="\\\\n"'); + expect(expression).toBe('csv input="stuff\nthings" separator="\\\\n"'); }); it('single expression with multiple and repeated arguments', () => { @@ -282,12 +303,12 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal( + expect(expression).toBe( 'csv input="stuff\nthings" input="more,things\nmore,stuff" separator="\\\\n"' ); }); - it('single expression with expression argument', () => { + it('single expression with `getcalc` expression argument', () => { const astObj = { type: 'expression', chain: [ @@ -314,10 +335,10 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv calc={getcalc} input="stuff\nthings"'); + expect(expression).toBe('csv calc={getcalc} input="stuff\nthings"'); }); - it('single expression with expression argument', () => { + it('single expression with `partcalc` expression argument', () => { const astObj = { type: 'expression', chain: [ @@ -344,7 +365,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('csv calc={partcalc} input="stuff\nthings"'); + expect(expression).toBe('csv calc={partcalc} input="stuff\nthings"'); }); it('single expression with expression arguments, with arguments', () => { @@ -390,7 +411,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal( + expect(expression).toBe( 'csv sep={partcalc type="comma"} input="stuff\nthings" break={setBreak type="newline"}' ); }); @@ -468,7 +489,7 @@ describe('ast toExpression', () => { '2016,honda,fit,15890,', '2016,honda,civic,18640"\n| line x={distinct f="year"} y={sum f="price"} colors={distinct f="model"}', ]; - expect(expression).to.equal(expected.join('\n')); + expect(expression).toBe(expected.join('\n')); }); it('three chained expressions', () => { @@ -563,7 +584,7 @@ describe('ast toExpression', () => { '2016,honda,civic,18640"\n| pointseries x={distinct f="year"} y={sum f="price"} ' + 'colors={distinct f="model"}\n| line pallette={getColorPallette name="elastic"}', ]; - expect(expression).to.equal(expected.join('\n')); + expect(expression).toBe(expected.join('\n')); }); }); @@ -583,7 +604,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('list "one" "two" "three"'); + expect(expression).toBe('list "one" "two" "three"'); }); it('named and unnamed', () => { @@ -603,7 +624,7 @@ describe('ast toExpression', () => { }; const expression = toExpression(astObj); - expect(expression).to.equal('both named="example" another="item" "one" "two" "three"'); + expect(expression).toBe('both named="example" another="item" "one" "two" "three"'); }); }); }); diff --git a/x-pack/plugins/canvas/common/lib/fn.js b/packages/kbn-interpreter/common/lib/fn.js similarity index 54% rename from x-pack/plugins/canvas/common/lib/fn.js rename to packages/kbn-interpreter/common/lib/fn.js index 70948c76579b3..c6b2fcbe67799 100644 --- a/x-pack/plugins/canvas/common/lib/fn.js +++ b/packages/kbn-interpreter/common/lib/fn.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 { mapValues, includes } from 'lodash'; diff --git a/packages/kbn-interpreter/common/lib/functions_registry.js b/packages/kbn-interpreter/common/lib/functions_registry.js new file mode 100644 index 0000000000000..1c71707d84722 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/functions_registry.js @@ -0,0 +1,29 @@ +/* + * 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 { Registry } from './registry'; +import { Fn } from './fn'; + +class FunctionsRegistry extends Registry { + wrapper(obj) { + return new Fn(obj); + } +} + +export const functionsRegistry = new FunctionsRegistry(); diff --git a/packages/kbn-interpreter/common/lib/get_by_alias.js b/packages/kbn-interpreter/common/lib/get_by_alias.js new file mode 100644 index 0000000000000..d7bb1bbf9e79d --- /dev/null +++ b/packages/kbn-interpreter/common/lib/get_by_alias.js @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/** + * This is used for looking up function/argument definitions. It looks through + * the given object/array for a case-insensitive match, which could be either the + * `name` itself, or something under the `aliases` property. + */ +export function getByAlias(specs, name) { + const lowerCaseName = name.toLowerCase(); + return Object.values(specs).find(({ name, aliases }) => { + if (name.toLowerCase() === lowerCaseName) return true; + return (aliases || []).some(alias => { + return alias.toLowerCase() === lowerCaseName; + }); + }); +} diff --git a/packages/kbn-interpreter/common/lib/get_by_alias.test.js b/packages/kbn-interpreter/common/lib/get_by_alias.test.js new file mode 100644 index 0000000000000..9cfc37fd8f304 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/get_by_alias.test.js @@ -0,0 +1,86 @@ +/* + * 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 { getByAlias } from './get_by_alias'; + +describe('getByAlias', () => { + const fnsObject = { + foo: { name: 'foo', aliases: ['f'] }, + bar: { name: 'bar', aliases: ['b'] }, + }; + + const fnsArray = [{ name: 'foo', aliases: ['f'] }, { name: 'bar', aliases: ['b'] }]; + + it('returns the function by name', () => { + expect(getByAlias(fnsObject, 'foo')).toBe(fnsObject.foo); + expect(getByAlias(fnsObject, 'bar')).toBe(fnsObject.bar); + expect(getByAlias(fnsArray, 'foo')).toBe(fnsArray[0]); + expect(getByAlias(fnsArray, 'bar')).toBe(fnsArray[1]); + }); + + it('returns the function by alias', () => { + expect(getByAlias(fnsObject, 'f')).toBe(fnsObject.foo); + expect(getByAlias(fnsObject, 'b')).toBe(fnsObject.bar); + expect(getByAlias(fnsArray, 'f')).toBe(fnsArray[0]); + expect(getByAlias(fnsArray, 'b')).toBe(fnsArray[1]); + }); + + it('returns the function by case-insensitive name', () => { + expect(getByAlias(fnsObject, 'FOO')).toBe(fnsObject.foo); + expect(getByAlias(fnsObject, 'BAR')).toBe(fnsObject.bar); + expect(getByAlias(fnsArray, 'FOO')).toBe(fnsArray[0]); + expect(getByAlias(fnsArray, 'BAR')).toBe(fnsArray[1]); + }); + + it('returns the function by case-insensitive alias', () => { + expect(getByAlias(fnsObject, 'F')).toBe(fnsObject.foo); + expect(getByAlias(fnsObject, 'B')).toBe(fnsObject.bar); + expect(getByAlias(fnsArray, 'F')).toBe(fnsArray[0]); + expect(getByAlias(fnsArray, 'B')).toBe(fnsArray[1]); + }); + + it('handles empty strings', () => { + const emptyStringFnsObject = { '': { name: '' } }; + const emptyStringAliasFnsObject = { foo: { name: 'foo', aliases: [''] } }; + expect(getByAlias(emptyStringFnsObject, '')).toBe(emptyStringFnsObject['']); + expect(getByAlias(emptyStringAliasFnsObject, '')).toBe(emptyStringAliasFnsObject.foo); + + const emptyStringFnsArray = [{ name: '' }]; + const emptyStringAliasFnsArray = [{ name: 'foo', aliases: [''] }]; + expect(getByAlias(emptyStringFnsArray, '')).toBe(emptyStringFnsArray[0]); + expect(getByAlias(emptyStringAliasFnsArray, '')).toBe(emptyStringAliasFnsArray[0]); + }); + + it('handles "undefined" strings', () => { + const undefinedFnsObject = { undefined: { name: 'undefined' } }; + const undefinedAliasFnsObject = { foo: { name: 'undefined', aliases: ['undefined'] } }; + expect(getByAlias(undefinedFnsObject, 'undefined')).toBe(undefinedFnsObject.undefined); + expect(getByAlias(undefinedAliasFnsObject, 'undefined')).toBe(undefinedAliasFnsObject.foo); + + const emptyStringFnsArray = [{ name: 'undefined' }]; + const emptyStringAliasFnsArray = [{ name: 'foo', aliases: ['undefined'] }]; + expect(getByAlias(emptyStringFnsArray, 'undefined')).toBe(emptyStringFnsArray[0]); + expect(getByAlias(emptyStringAliasFnsArray, 'undefined')).toBe(emptyStringAliasFnsArray[0]); + }); + + it('returns undefined if not found', () => { + expect(getByAlias(fnsObject, 'baz')).toBe(undefined); + expect(getByAlias(fnsArray, 'baz')).toBe(undefined); + }); +}); diff --git a/packages/kbn-interpreter/common/lib/get_type.js b/packages/kbn-interpreter/common/lib/get_type.js new file mode 100644 index 0000000000000..ac440acf8da5d --- /dev/null +++ b/packages/kbn-interpreter/common/lib/get_type.js @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export function getType(node) { + if (node == null) return 'null'; + if (typeof node === 'object') { + if (!node.type) throw new Error('Objects must have a type property'); + return node.type; + } + + return typeof node; +} diff --git a/x-pack/plugins/canvas/common/lib/grammar.js b/packages/kbn-interpreter/common/lib/grammar.js similarity index 100% rename from x-pack/plugins/canvas/common/lib/grammar.js rename to packages/kbn-interpreter/common/lib/grammar.js diff --git a/x-pack/plugins/canvas/common/lib/grammar.peg b/packages/kbn-interpreter/common/lib/grammar.peg similarity index 100% rename from x-pack/plugins/canvas/common/lib/grammar.peg rename to packages/kbn-interpreter/common/lib/grammar.peg diff --git a/packages/kbn-interpreter/common/lib/paths_registry.js b/packages/kbn-interpreter/common/lib/paths_registry.js new file mode 100644 index 0000000000000..3ad2b5dddf82e --- /dev/null +++ b/packages/kbn-interpreter/common/lib/paths_registry.js @@ -0,0 +1,65 @@ +/* + * 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. + */ + +class PathsRegistry { + + constructor() { + this.paths = new Map(); + } + + register = (type, paths) => { + if (!type) { + throw new Error(`Register requires a type`); + } + const lowerCaseType = type.toLowerCase(); + + const pathArray = Array.isArray(paths) ? paths : [paths]; + if (!this.paths.has(lowerCaseType)) { + this.paths.set(lowerCaseType, []); + } + + pathArray.forEach(p => { + this.paths.get(lowerCaseType).push(p); + }); + }; + + registerAll = (paths) => { + Object.keys(paths).forEach(type => { + this.register(type, paths[type]); + }); + }; + + toArray = () => { + return [...this.paths.values()]; + }; + + get = (type) => { + if (!type) { + return []; + } + const lowerCaseType = type.toLowerCase(); + return this.paths.has(lowerCaseType) ? this.paths.get(lowerCaseType) : []; + }; + + reset = () => { + this.paths.clear(); + }; +} + +export const pathsRegistry = new PathsRegistry(); diff --git a/packages/kbn-interpreter/common/lib/paths_registry.test.js b/packages/kbn-interpreter/common/lib/paths_registry.test.js new file mode 100644 index 0000000000000..ad2b9d949deb3 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/paths_registry.test.js @@ -0,0 +1,92 @@ +/* + * 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. + */ + +describe('pathsRegistry', () => { + let registry; + beforeEach(() => { + jest.resetModules(); + registry = require('./paths_registry').pathsRegistry; + }); + + const paths = { + foo: 'bar', + sometype: [ + 'Here', + 'be', + 'more', + 'paths!' + ], + anothertype: ['with just one lonely path'] + }; + + it('throws when no type is provided', () => { + const check = () => registry.register(null, paths.foo); + expect(check).toThrowError(/requires a type/); + }); + + it('accepts paths as a string', () => { + registry.register('foo', paths.foo); + expect(registry.get('foo')).toEqual([paths.foo]); + }); + + it('accepts paths as an array', () => { + registry.register('sometype', paths.sometype); + expect(registry.get('sometype')).toEqual(paths.sometype); + }); + + it('ignores case when setting items', () => { + registry.register('FOO', paths.foo); + expect(registry.get('foo')).toEqual([paths.foo]); + }); + + it('gets items by lookup property', () => { + registry.register('sometype', paths.sometype); + expect(registry.get('sometype')).toEqual(paths.sometype); + }); + + it('can register an object of `type: path` key-value pairs', () => { + registry.registerAll(paths); + expect(registry.get('foo')).toEqual([paths.foo]); + expect(registry.get('sometype')).toEqual(paths.sometype); + expect(registry.get('anothertype')).toEqual(paths.anothertype); + }); + + it('ignores case when getting items', () => { + registry.registerAll(paths); + expect(registry.get('FOO')).toEqual([paths.foo]); + expect(registry.get('SOmEType')).toEqual(paths.sometype); + expect(registry.get('anoThertYPE')).toEqual(paths.anothertype); + }); + + it('returns an empty array with no match', () => { + expect(registry.get('@@nope_nope')).toEqual([]); + }); + + it('returns an array of all path values', () => { + registry.registerAll(paths); + expect(registry.toArray()).toEqual([[paths.foo], paths.sometype, paths.anothertype]); + }); + + it('resets the registry', () => { + registry.registerAll(paths); + expect(registry.get('sometype')).toEqual(paths.sometype); + registry.reset(); + expect(registry.get('sometype')).toEqual([]); + }); +}); \ No newline at end of file diff --git a/x-pack/plugins/canvas/common/lib/registry.js b/packages/kbn-interpreter/common/lib/registry.js similarity index 56% rename from x-pack/plugins/canvas/common/lib/registry.js rename to packages/kbn-interpreter/common/lib/registry.js index accabae4bc5eb..9882f3abde723 100644 --- a/x-pack/plugins/canvas/common/lib/registry.js +++ b/packages/kbn-interpreter/common/lib/registry.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 clone from 'lodash.clone'; @@ -22,8 +35,9 @@ export class Registry { const obj = fn(); - if (typeof obj !== 'object' || !obj[this._prop]) + if (typeof obj !== 'object' || !obj[this._prop]) { throw new Error(`Registered functions must return an object with a ${this._prop} property`); + } this._indexed[obj[this._prop].toLowerCase()] = this.wrapper(obj); } diff --git a/x-pack/plugins/canvas/common/lib/__tests__/registry.js b/packages/kbn-interpreter/common/lib/registry.test.js similarity index 60% rename from x-pack/plugins/canvas/common/lib/__tests__/registry.js rename to packages/kbn-interpreter/common/lib/registry.test.js index fd19bf0300417..dbeeb16dc1ff0 100644 --- a/x-pack/plugins/canvas/common/lib/__tests__/registry.js +++ b/packages/kbn-interpreter/common/lib/registry.test.js @@ -1,51 +1,63 @@ /* - * 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. + * 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 expect from 'expect.js'; -import { Registry } from '../registry'; +import { Registry } from './registry'; function validateRegistry(registry, elements) { it('gets items by lookup property', () => { - expect(registry.get('__test2')).to.eql(elements[1]()); + expect(registry.get('__test2')).toEqual(elements[1]()); }); it('ignores case when getting items', () => { - expect(registry.get('__TeSt2')).to.eql(elements[1]()); - expect(registry.get('__tESt2')).to.eql(elements[1]()); + expect(registry.get('__TeSt2')).toEqual(elements[1]()); + expect(registry.get('__tESt2')).toEqual(elements[1]()); }); it('gets a shallow clone', () => { - expect(registry.get('__test2')).to.not.equal(elements[1]()); + expect(registry.get('__test2')).not.toBe(elements[1]()); }); it('is null with no match', () => { - expect(registry.get('@@nope_nope')).to.be(null); + expect(registry.get('@@nope_nope')).toBe(null); }); it('returns shallow clone of the whole registry via toJS', () => { const regAsJs = registry.toJS(); - expect(regAsJs).to.eql({ + expect(regAsJs).toEqual({ __test1: elements[0](), __test2: elements[1](), }); - expect(regAsJs.__test1).to.eql(elements[0]()); - expect(regAsJs.__test1).to.not.equal(elements[0]()); + expect(regAsJs.__test1).toEqual(elements[0]()); + expect(regAsJs.__test1).not.toBe(elements[0]()); }); it('returns shallow clone array via toArray', () => { const regAsArray = registry.toArray(); - expect(regAsArray).to.be.an(Array); - expect(regAsArray[0]).to.eql(elements[0]()); - expect(regAsArray[0]).to.not.equal(elements[0]()); + expect(regAsArray).toBeInstanceOf(Array); + expect(regAsArray[0]).toEqual(elements[0]()); + expect(regAsArray[0]).not.toBe(elements[0]()); }); it('resets the registry', () => { - expect(registry.get('__test2')).to.eql(elements[1]()); + expect(registry.get('__test2')).toEqual(elements[1]()); registry.reset(); - expect(registry.get('__test2')).to.equal(null); + expect(registry.get('__test2')).toBe(null); }); } @@ -70,12 +82,12 @@ describe('Registry', () => { validateRegistry(registry, elements); it('has a prop of name', () => { - expect(registry.getProp()).to.equal('name'); + expect(registry.getProp()).toBe('name'); }); it('throws when object is missing the lookup prop', () => { const check = () => registry.register(() => ({ hello: 'world' })); - expect(check).to.throwException(/object with a name property/i); + expect(check).toThrowError(/object with a name property/); }); }); @@ -99,12 +111,12 @@ describe('Registry', () => { validateRegistry(registry, elements); it('has a prop of type', () => { - expect(registry.getProp()).to.equal('type'); + expect(registry.getProp()).toBe('type'); }); it('throws when object is missing the lookup prop', () => { const check = () => registry.register(() => ({ hello: 'world' })); - expect(check).to.throwException(/object with a type property/i); + expect(check).toThrowError(/object with a type property/); }); }); @@ -137,9 +149,8 @@ describe('Registry', () => { registry.register(elements[1]); it('contains wrapped elements', () => { - // test for the custom prop on the returned elements - expect(registry.get(elements[0]().name)).to.have.property('__CUSTOM_PROP__', 1); - expect(registry.get(elements[1]().name)).to.have.property('__CUSTOM_PROP__', 2); + expect(registry.get(elements[0]().name)).toHaveProperty('__CUSTOM_PROP__'); + expect(registry.get(elements[1]().name)).toHaveProperty('__CUSTOM_PROP__'); }); }); @@ -171,20 +182,18 @@ describe('Registry', () => { }); it('get contains the full prototype', () => { - expect(thing().baseFunc).to.be.a('function'); - expect(registry.get(name).baseFunc).to.be.a('function'); + expect(typeof thing().baseFunc).toBe('function'); + expect(typeof registry.get(name).baseFunc).toBe('function'); }); it('toJS contains the full prototype', () => { const val = registry.toJS(); - expect(val[name].baseFunc).to.be.a('function'); + expect(typeof val[name].baseFunc).toBe('function'); }); }); describe('throws when lookup prop is not a string', () => { const check = () => new Registry(2); - expect(check).to.throwException(e => { - expect(e.message).to.be('Registry property name must be a string'); - }); + expect(check).toThrowError(/must be a string/); }); }); diff --git a/packages/kbn-interpreter/common/lib/serialize.js b/packages/kbn-interpreter/common/lib/serialize.js new file mode 100644 index 0000000000000..2f881db3c77e0 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/serialize.js @@ -0,0 +1,37 @@ +/* + * 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 { get, identity } from 'lodash'; +import { getType } from './get_type'; + +export function serializeProvider(types) { + return { + serialize: provider('serialize'), + deserialize: provider('deserialize'), + }; + + function provider(key) { + return context => { + const type = getType(context); + const typeDef = types[type]; + const fn = get(typeDef, key) || identity; + return fn(context); + }; + } +} diff --git a/x-pack/plugins/canvas/common/lib/type.js b/packages/kbn-interpreter/common/lib/type.js similarity index 61% rename from x-pack/plugins/canvas/common/lib/type.js rename to packages/kbn-interpreter/common/lib/type.js index d917750e3848e..356b82bf91cbd 100644 --- a/x-pack/plugins/canvas/common/lib/type.js +++ b/packages/kbn-interpreter/common/lib/type.js @@ -1,12 +1,25 @@ /* - * 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. + * 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. */ // All types must be universal and be castable on the client or on the server import { get } from 'lodash'; -import { getType } from '../lib/get_type'; +import { getType } from './get_type'; // TODO: Currently all casting functions must be syncronous. @@ -35,10 +48,12 @@ export function Type(config) { this.to = (node, toTypeName, types) => { const typeName = getType(node); - if (typeName !== this.name) + if (typeName !== this.name) { throw new Error(`Can not cast object of type '${typeName}' using '${this.name}'`); - else if (!this.castsTo(toTypeName)) + } + else if (!this.castsTo(toTypeName)) { throw new Error(`Can not cast '${typeName}' to '${toTypeName}'`); + } return getToFn(toTypeName)(node, types); }; diff --git a/packages/kbn-interpreter/common/lib/types_registry.js b/packages/kbn-interpreter/common/lib/types_registry.js new file mode 100644 index 0000000000000..97e28875d7e20 --- /dev/null +++ b/packages/kbn-interpreter/common/lib/types_registry.js @@ -0,0 +1,29 @@ +/* + * 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 { Registry } from './registry'; +import { Type } from './type'; + +class TypesRegistry extends Registry { + wrapper(obj) { + return new Type(obj); + } +} + +export const typesRegistry = new TypesRegistry(); diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json new file mode 100644 index 0000000000000..0178b9e2cfe32 --- /dev/null +++ b/packages/kbn-interpreter/package.json @@ -0,0 +1,10 @@ +{ + "name": "@kbn/interpreter", + "version": "1.0.0", + "license": "Apache-2.0", + "scripts": { + "build": "node tasks/build.js", + "canvas:peg": "pegjs common/lib/grammar.peg", + "kbn:bootstrap": "yarn build" + } +} diff --git a/packages/kbn-interpreter/plugin_src/functions/common/clog.js b/packages/kbn-interpreter/plugin_src/functions/common/clog.js new file mode 100644 index 0000000000000..634d166f5f0bb --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/functions/common/clog.js @@ -0,0 +1,27 @@ +/* + * 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. + */ + +export const clog = () => ({ + name: 'clog', + help: 'Outputs the context to the console', + fn: context => { + console.log(context); //eslint-disable-line no-console + return context; + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/functions/common/index.js b/packages/kbn-interpreter/plugin_src/functions/common/index.js new file mode 100644 index 0000000000000..2f5f91181faec --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/functions/common/index.js @@ -0,0 +1,24 @@ +/* + * 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 { clog } from './clog'; + +export const commonFunctions = [ + clog, +]; diff --git a/packages/kbn-interpreter/plugin_src/functions/common/register.js b/packages/kbn-interpreter/plugin_src/functions/common/register.js new file mode 100644 index 0000000000000..8b146b8f849c3 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/functions/common/register.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 { commonFunctions } from './index'; + +// eslint-disable-next-line no-undef +commonFunctions.forEach(canvas.register); diff --git a/packages/kbn-interpreter/plugin_src/types/boolean.js b/packages/kbn-interpreter/plugin_src/types/boolean.js new file mode 100644 index 0000000000000..cc5f0a79e39a8 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/boolean.js @@ -0,0 +1,42 @@ +/* + * 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. + */ + +export const boolean = () => ({ + name: 'boolean', + from: { + null: () => false, + number: n => Boolean(n), + string: s => Boolean(s), + }, + to: { + render: value => { + const text = `${value}`; + return { + type: 'render', + as: 'text', + value: { text }, + }; + }, + datatable: value => ({ + type: 'datatable', + columns: [{ name: 'value', type: 'boolean' }], + rows: [{ value }], + }), + }, +}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/datatable.js b/packages/kbn-interpreter/plugin_src/types/datatable.js similarity index 63% rename from x-pack/plugins/canvas/canvas_plugin_src/types/datatable.js rename to packages/kbn-interpreter/plugin_src/types/datatable.js index cfe75605f1ebf..92bd2c9b1b59e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/datatable.js +++ b/packages/kbn-interpreter/plugin_src/types/datatable.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 { map, zipObject } from 'lodash'; @@ -10,8 +23,9 @@ export const datatable = () => ({ name: 'datatable', validate: datatable => { // TODO: Check columns types. Only string, boolean, number, date, allowed for now. - if (!datatable.columns) + if (!datatable.columns) { throw new Error('datatable must have a columns array, even if it is empty'); + } if (!datatable.rows) throw new Error('datatable must have a rows array, even if it is empty'); }, diff --git a/packages/kbn-interpreter/plugin_src/types/error.js b/packages/kbn-interpreter/plugin_src/types/error.js new file mode 100644 index 0000000000000..1415a065d810e --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/error.js @@ -0,0 +1,35 @@ +/* + * 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. + */ + +export const error = () => ({ + name: 'error', + to: { + render: input => { + const { error, info } = input; + return { + type: 'render', + as: 'error', + value: { + error, + info, + }, + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/filter.js b/packages/kbn-interpreter/plugin_src/types/filter.js new file mode 100644 index 0000000000000..484050671b2f9 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/filter.js @@ -0,0 +1,33 @@ +/* + * 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. + */ + +export const filter = () => ({ + name: 'filter', + from: { + null: () => { + return { + type: 'filter', + // Any meta data you wish to pass along. + meta: {}, + // And filters. If you need an "or", create a filter type for it. + and: [], + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/image.js b/packages/kbn-interpreter/plugin_src/types/image.js new file mode 100644 index 0000000000000..7666451145f5d --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/image.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +export const image = () => ({ + name: 'image', + to: { + render: input => { + return { + type: 'render', + as: 'image', + value: input, + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/index.js b/packages/kbn-interpreter/plugin_src/types/index.js new file mode 100644 index 0000000000000..1ae5f874835c3 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/index.js @@ -0,0 +1,46 @@ +/* + * 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 { boolean } from './boolean'; +import { datatable } from './datatable'; +import { error } from './error'; +import { filter } from './filter'; +import { image } from './image'; +import { nullType } from './null'; +import { number } from './number'; +import { pointseries } from './pointseries'; +import { render } from './render'; +import { shape } from './shape'; +import { string } from './string'; +import { style } from './style'; + +export const typeSpecs = [ + boolean, + datatable, + error, + filter, + image, + number, + nullType, + pointseries, + render, + shape, + string, + style, +]; diff --git a/packages/kbn-interpreter/plugin_src/types/null.js b/packages/kbn-interpreter/plugin_src/types/null.js new file mode 100644 index 0000000000000..2789ce330ac6c --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/null.js @@ -0,0 +1,25 @@ +/* + * 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. + */ + +export const nullType = () => ({ + name: 'null', + from: { + '*': () => null, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/number.js b/packages/kbn-interpreter/plugin_src/types/number.js new file mode 100644 index 0000000000000..8f8f31ea8a2fb --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/number.js @@ -0,0 +1,42 @@ +/* + * 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. + */ + +export const number = () => ({ + name: 'number', + from: { + null: () => 0, + boolean: b => Number(b), + string: n => Number(n), + }, + to: { + render: value => { + const text = `${value}`; + return { + type: 'render', + as: 'text', + value: { text }, + }; + }, + datatable: value => ({ + type: 'datatable', + columns: [{ name: 'value', type: 'number' }], + rows: [{ value }], + }), + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/pointseries.js b/packages/kbn-interpreter/plugin_src/types/pointseries.js new file mode 100644 index 0000000000000..2275ea9e04094 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/pointseries.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +export const pointseries = () => ({ + name: 'pointseries', + from: { + null: () => { + return { + type: 'pointseries', + rows: [], + columns: [], + }; + }, + }, + to: { + render: (pointseries, types) => { + const datatable = types.datatable.from(pointseries, types); + return { + type: 'render', + as: 'table', + value: { + datatable, + showHeader: true, + }, + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/register.js b/packages/kbn-interpreter/plugin_src/types/register.js new file mode 100644 index 0000000000000..17b03f0229672 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/register.js @@ -0,0 +1,24 @@ +/* + * 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 'babel-polyfill'; +import { typeSpecs } from './index'; + +// eslint-disable-next-line no-undef +typeSpecs.forEach(canvas.register); diff --git a/packages/kbn-interpreter/plugin_src/types/render.js b/packages/kbn-interpreter/plugin_src/types/render.js new file mode 100644 index 0000000000000..99ce3ca7d1cd7 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/render.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +export const render = () => ({ + name: 'render', + from: { + '*': v => ({ + type: 'render', + as: 'debug', + value: v, + }), + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/shape.js b/packages/kbn-interpreter/plugin_src/types/shape.js new file mode 100644 index 0000000000000..1ed7a111268d1 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/shape.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +export const shape = () => ({ + name: 'shape', + to: { + render: input => { + return { + type: 'render', + as: 'shape', + value: input, + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/string.js b/packages/kbn-interpreter/plugin_src/types/string.js new file mode 100644 index 0000000000000..90e6b17cc9dcf --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/string.js @@ -0,0 +1,41 @@ +/* + * 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. + */ + +export const string = () => ({ + name: 'string', + from: { + null: () => '', + boolean: b => String(b), + number: n => String(n), + }, + to: { + render: text => { + return { + type: 'render', + as: 'text', + value: { text }, + }; + }, + datatable: value => ({ + type: 'datatable', + columns: [{ name: 'value', type: 'string' }], + rows: [{ value }], + }), + }, +}); diff --git a/packages/kbn-interpreter/plugin_src/types/style.js b/packages/kbn-interpreter/plugin_src/types/style.js new file mode 100644 index 0000000000000..97057b415a475 --- /dev/null +++ b/packages/kbn-interpreter/plugin_src/types/style.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +export const style = () => ({ + name: 'style', + from: { + null: () => { + return { + type: 'style', + spec: {}, + css: '', + }; + }, + }, +}); diff --git a/packages/kbn-interpreter/public/browser_registries.js b/packages/kbn-interpreter/public/browser_registries.js new file mode 100644 index 0000000000000..778a0b03a7624 --- /dev/null +++ b/packages/kbn-interpreter/public/browser_registries.js @@ -0,0 +1,83 @@ +/* + * 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 chrome from 'ui/chrome'; +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) => { + const remainingTypes = Object.keys(registries); + const populatedTypes = {}; + + return new Promise(resolve => { + function loadType() { + if (!remainingTypes.length) { + resolve(populatedTypes); + return; + } + const type = remainingTypes.pop(); + window.canvas = window.canvas || {}; + window.canvas.register = d => registries[type].register(d); + + // Load plugins one at a time because each needs a different loader function + // $script will only load each of these once, we so can call this as many times as we need? + const pluginPath = chrome.addBasePath(`/api/canvas/plugins?type=${type}`); + $script(pluginPath, () => { + populatedTypes[type] = registries[type]; + loadType(); + }); + } + + loadType(); + }); +}; + +export const populateBrowserRegistries = (registries) => { + if (called) { + const oldPromise = populatePromise; + let newResolve; + populatePromise = new Promise(_resolve => { + newResolve = _resolve; + }); + oldPromise.then(oldTypes => { + loadBrowserRegistries(registries).then(newTypes => { + newResolve({ + ...oldTypes, + ...newTypes, + }); + }); + }); + return populatePromise; + } + called = true; + loadBrowserRegistries(registries).then(registries => { + resolvePromise(registries); + }); + return populatePromise; +}; diff --git a/packages/kbn-interpreter/public/create_handlers.js b/packages/kbn-interpreter/public/create_handlers.js new file mode 100644 index 0000000000000..3446a945ae76e --- /dev/null +++ b/packages/kbn-interpreter/public/create_handlers.js @@ -0,0 +1,24 @@ +/* + * 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. + */ + +export function createHandlers(/*socket*/) { + return { + environment: 'client', + }; +} diff --git a/x-pack/plugins/canvas/public/lib/interpreter.js b/packages/kbn-interpreter/public/interpreter.js similarity index 55% rename from x-pack/plugins/canvas/public/lib/interpreter.js rename to packages/kbn-interpreter/public/interpreter.js index 36878871b8b15..5c1e199bce363 100644 --- a/x-pack/plugins/canvas/public/lib/interpreter.js +++ b/packages/kbn-interpreter/public/interpreter.js @@ -1,15 +1,28 @@ /* - * 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. + * 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 { socketInterpreterProvider } from '../../common/interpreter/socket_interpret'; -import { serializeProvider } from '../../common/lib/serialize'; -import { getSocket } from '../socket'; -import { typesRegistry } from '../../common/lib/types_registry'; +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 './functions_registry'; +import { functionsRegistry } from '../common/lib/functions_registry'; import { getBrowserRegistries } from './browser_registries'; let socket; diff --git a/x-pack/plugins/canvas/public/socket.js b/packages/kbn-interpreter/public/socket.js similarity index 64% rename from x-pack/plugins/canvas/public/socket.js rename to packages/kbn-interpreter/public/socket.js index 92deedd488c06..9143f0018377b 100644 --- a/x-pack/plugins/canvas/public/socket.js +++ b/packages/kbn-interpreter/public/socket.js @@ -1,12 +1,25 @@ /* - * 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. + * 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 io from 'socket.io-client'; import { functionsRegistry } from '../common/lib/functions_registry'; -import { getBrowserRegistries } from './lib/browser_registries'; +import { getBrowserRegistries } from './browser_registries'; const SOCKET_CONNECTION_TIMEOUT = 5000; // timeout in ms let socket; diff --git a/packages/kbn-interpreter/server/get_plugin_paths.js b/packages/kbn-interpreter/server/get_plugin_paths.js new file mode 100644 index 0000000000000..f6520563c912f --- /dev/null +++ b/packages/kbn-interpreter/server/get_plugin_paths.js @@ -0,0 +1,55 @@ +/* + * 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 fs from 'fs'; +import { resolve } from 'path'; +import { promisify } from 'util'; +import { flatten } from 'lodash'; +import { pathsRegistry } from '../common/lib/paths_registry'; + +const lstat = promisify(fs.lstat); +const readdir = promisify(fs.readdir); + +const isDirectory = path => + lstat(path) + .then(stat => stat.isDirectory()) + .catch(() => false); + +export const getPluginPaths = type => { + const typePaths = pathsRegistry.get(type); + if (!typePaths) { + throw new Error(`Unknown type: ${type}`); + } + + return Promise.all(typePaths.map(async path => { + const isDir = await isDirectory(path); + if (!isDir) { + return; + } + // Get the full path of all js files in the directory + return readdir(path).then(files => { + return files.reduce((acc, file) => { + if (file.endsWith('.js')) { + acc.push(resolve(path, file)); + } + return acc; + }, []); + }).catch(); + })).then(flatten); +}; diff --git a/packages/kbn-interpreter/server/server_registries.js b/packages/kbn-interpreter/server/server_registries.js new file mode 100644 index 0000000000000..3fbb957673e63 --- /dev/null +++ b/packages/kbn-interpreter/server/server_registries.js @@ -0,0 +1,78 @@ +/* + * 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 '../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; + +const populatePromise = new Promise(_resolve => { + resolve = _resolve; +}); + +export const getServerRegistries = () => { + return populatePromise; +}; + +export const populateServerRegistries = types => { + if (called) { + console.log('function should only be called once per process'); + return populatePromise; + } + called = true; + if (!types || !types.length) throw new Error('types is required'); + + const remainingTypes = types; + const populatedTypes = {}; + + const globalKeys = Object.keys(global); + + 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); + }); + + Object.keys(global).forEach(key => { + if (!globalKeys.includes(key)) { + delete global[key]; + } + }); + + populatedTypes[type] = registries[type]; + if (remainingTypes.length) loadType(); + else resolve(populatedTypes); + }); + }; + + if (remainingTypes.length) loadType(); + return populatePromise; +}; diff --git a/packages/kbn-interpreter/tasks/build.js b/packages/kbn-interpreter/tasks/build.js new file mode 100644 index 0000000000000..37776e8d74cca --- /dev/null +++ b/packages/kbn-interpreter/tasks/build.js @@ -0,0 +1,40 @@ +/* + * 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 webpack = require('webpack'); +const webpackConfig = require('./webpack.plugins'); + +const devtool = 'inline-cheap-module-source-map'; + +const onComplete = function (done) { + return function (err, stats) { + if (err) { + done && done(err); + } else { + const seconds = ((stats.endTime - stats.startTime) / 1000).toFixed(2); + console.log(`Plugins built in ${seconds} seconds`); + done && done(); + } + }; +}; + +webpack({ ...webpackConfig, devtool }, onComplete(function () { + console.log('all done'); +})); + diff --git a/packages/kbn-interpreter/tasks/webpack.plugins.js b/packages/kbn-interpreter/tasks/webpack.plugins.js new file mode 100644 index 0000000000000..8b16edc5ad462 --- /dev/null +++ b/packages/kbn-interpreter/tasks/webpack.plugins.js @@ -0,0 +1,100 @@ +/* + * 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 path = require('path'); + +const sourceDir = path.resolve(__dirname, '../plugin_src'); +const buildDir = path.resolve(__dirname, '../plugin'); + +module.exports = { + entry: { + 'types/all': path.join(sourceDir, 'types/register.js'), + 'functions/common/all': path.join(sourceDir, 'functions/common/register.js'), + }, + target: 'webworker', + + output: { + path: buildDir, + filename: '[name].js', // Need long paths here. + libraryTarget: 'umd', + }, + + resolve: { + extensions: ['.js', '.json'], + mainFields: ['browser', 'main'], + }, + + plugins: [ + function loaderFailHandler() { + // bails on error, including loader errors + // see https://github.com/webpack/webpack/issues/708, which does not fix loader errors + let isWatch = true; + + this.plugin('run', function (compiler, callback) { + isWatch = false; + callback.call(compiler); + }); + + this.plugin('done', function (stats) { + if (!stats.hasErrors()) { + return; + } + const errorMessage = stats.toString('errors-only'); + if (isWatch) { + console.error(errorMessage); + } + else { + throw new Error(errorMessage); + } + }); + }, + ], + + module: { + rules: [ + { + test: /\.js$/, + exclude: [/node_modules/], + loaders: 'babel-loader', + options: { + babelrc: false, + presets: [require.resolve('@kbn/babel-preset/webpack_preset')], + }, + }, + { + test: /\.(png|jpg|gif|jpeg|svg)$/, + loaders: ['url-loader'], + }, + { + test: /\.(css|scss)$/, + loaders: ['style-loader', 'css-loader', 'sass-loader'], + }, + ], + }, + + node: { + // Don't replace built-in globals + __filename: false, + __dirname: false, + }, + + watchOptions: { + ignored: [/node_modules/], + }, +}; diff --git a/src/core_plugins/interpreter/common/constants.js b/src/core_plugins/interpreter/common/constants.js new file mode 100644 index 0000000000000..a5751ee72e826 --- /dev/null +++ b/src/core_plugins/interpreter/common/constants.js @@ -0,0 +1,21 @@ +/* + * 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. + */ + +export const SECURITY_AUTH_MESSAGE = 'Authentication failed'; +export const API_ROUTE = '/api/canvas'; diff --git a/src/core_plugins/interpreter/index.js b/src/core_plugins/interpreter/index.js new file mode 100644 index 0000000000000..273c8b8c37957 --- /dev/null +++ b/src/core_plugins/interpreter/index.js @@ -0,0 +1,41 @@ +/* + * 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 { resolve } from 'path'; +import init from './init'; +import { pathsRegistry } from '@kbn/interpreter/common/lib/paths_registry'; +import { pluginPaths } from './plugin_paths'; + +export default function (kibana) { + return new kibana.Plugin({ + id: 'interpreter', + require: ['kibana', 'elasticsearch'], + publicDir: resolve(__dirname, 'public'), + uiExports: { + hacks: [ + 'plugins/interpreter/load_browser_plugins.js', + ], + }, + preInit: () => { + pathsRegistry.registerAll(pluginPaths); + }, + init, + }); +} + diff --git a/src/core_plugins/interpreter/init.js b/src/core_plugins/interpreter/init.js new file mode 100644 index 0000000000000..58385973ac930 --- /dev/null +++ b/src/core_plugins/interpreter/init.js @@ -0,0 +1,41 @@ +/* + * 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 { routes } from './server/routes'; +import { functionsRegistry } from '@kbn/interpreter/common/lib/functions_registry'; +import { populateServerRegistries } from '@kbn/interpreter/server/server_registries'; + +export default function (server /*options*/) { + server.injectUiAppVars('canvas', () => { + const config = server.config(); + const basePath = config.get('server.basePath'); + const reportingBrowserType = config.get('xpack.reporting.capture.browser.type'); + + return { + kbnIndex: config.get('kibana.index'), + esShardTimeout: config.get('elasticsearch.shardTimeout'), + esApiVersion: config.get('elasticsearch.apiVersion'), + serverFunctions: functionsRegistry.toArray(), + basePath, + reportingBrowserType, + }; + }); + + populateServerRegistries(['serverFunctions', 'types']).then(() => routes(server)); +} diff --git a/src/core_plugins/interpreter/package.json b/src/core_plugins/interpreter/package.json new file mode 100644 index 0000000000000..3265dadd7fbfc --- /dev/null +++ b/src/core_plugins/interpreter/package.json @@ -0,0 +1,4 @@ +{ + "name": "interpreter", + "version": "kibana" +} diff --git a/src/core_plugins/interpreter/plugin_paths.js b/src/core_plugins/interpreter/plugin_paths.js new file mode 100644 index 0000000000000..ca44ce1a1f7b2 --- /dev/null +++ b/src/core_plugins/interpreter/plugin_paths.js @@ -0,0 +1,27 @@ +/* + * 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 { resolve } from 'path'; + +const dir = resolve(__dirname, '..', '..', '..'); + +export const pluginPaths = { + commonFunctions: resolve(dir, 'node_modules/@kbn/interpreter/plugin/functions/common'), + types: resolve(dir, 'node_modules/@kbn/interpreter/plugin/types'), +}; diff --git a/src/core_plugins/interpreter/public/load_browser_plugins.js b/src/core_plugins/interpreter/public/load_browser_plugins.js new file mode 100644 index 0000000000000..6322e8e340e45 --- /dev/null +++ b/src/core_plugins/interpreter/public/load_browser_plugins.js @@ -0,0 +1,30 @@ +/* + * 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 { populateBrowserRegistries } from '@kbn/interpreter/public/browser_registries'; +import { typesRegistry } from '@kbn/interpreter/common/lib/types_registry'; +import { functionsRegistry } from '@kbn/interpreter/common/lib/functions_registry'; + +const types = { + commonFunctions: functionsRegistry, + browserFunctions: functionsRegistry, + types: typesRegistry +}; + +populateBrowserRegistries(types); diff --git a/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js b/src/core_plugins/interpreter/server/lib/__tests__/create_handlers.js similarity index 83% rename from x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js rename to src/core_plugins/interpreter/server/lib/__tests__/create_handlers.js index 9dbe0e413a1af..9afe458c444a7 100644 --- a/x-pack/plugins/canvas/server/lib/__tests__/create_handlers.js +++ b/src/core_plugins/interpreter/server/lib/__tests__/create_handlers.js @@ -1,12 +1,25 @@ /* - * 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. + * 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 expect from 'expect.js'; import { createHandlers } from '../create_handlers'; -import { SECURITY_AUTH_MESSAGE } from '../../../common/lib/constants'; +import { SECURITY_AUTH_MESSAGE } from '../../../common/constants'; let securityMode = 'pass'; let isSecurityAvailable = true; diff --git a/x-pack/plugins/canvas/server/lib/create_handlers.js b/src/core_plugins/interpreter/server/lib/create_handlers.js similarity index 58% rename from x-pack/plugins/canvas/server/lib/create_handlers.js rename to src/core_plugins/interpreter/server/lib/create_handlers.js index f42f8fbe1a59d..9c4dcd112c928 100644 --- a/x-pack/plugins/canvas/server/lib/create_handlers.js +++ b/src/core_plugins/interpreter/server/lib/create_handlers.js @@ -1,12 +1,25 @@ /* - * 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. + * 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 boom from 'boom'; -import { SECURITY_AUTH_MESSAGE } from '../../common/lib/constants'; import { isSecurityEnabled } from './feature_check'; +import { SECURITY_AUTH_MESSAGE } from '../../common/constants'; export const createHandlers = (request, server) => { const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); @@ -24,8 +37,9 @@ export const createHandlers = (request, server) => { if (isSecurityEnabled(server)) { try { const authenticationResult = await server.plugins.security.authenticate(request); - if (!authenticationResult.succeeded()) + if (!authenticationResult.succeeded()) { throw boom.unauthorized(authenticationResult.error); + } } catch (e) { // if authenticate throws, show error in development if (process.env.NODE_ENV !== 'production') { diff --git a/src/core_plugins/interpreter/server/lib/feature_check.js b/src/core_plugins/interpreter/server/lib/feature_check.js new file mode 100644 index 0000000000000..9f7a8993fa3ff --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/feature_check.js @@ -0,0 +1,26 @@ +/* + * 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. + */ + +// TODO: replace this when we use the method exposed by security https://github.com/elastic/kibana/pull/24616 +export const isSecurityEnabled = server => { + const kibanaSecurity = server.plugins.security; + const esSecurity = server.plugins.xpack_main.info.feature('security'); + + return kibanaSecurity && esSecurity.isAvailable() && esSecurity.isEnabled(); +}; diff --git a/src/core_plugins/interpreter/server/lib/get_plugin_stream.js b/src/core_plugins/interpreter/server/lib/get_plugin_stream.js new file mode 100644 index 0000000000000..d685d365d31a4 --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/get_plugin_stream.js @@ -0,0 +1,37 @@ +/* + * 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 fs from 'fs'; +import ss from 'stream-stream'; +import { getPluginPaths } from '@kbn/interpreter/server/get_plugin_paths'; + +export const getPluginStream = type => { + const stream = ss({ + separator: '\n', + }); + + getPluginPaths(type).then(files => { + files.forEach(file => { + stream.write(fs.createReadStream(file)); + }); + stream.end(); + }); + + return stream; +}; diff --git a/src/core_plugins/interpreter/server/lib/get_request.js b/src/core_plugins/interpreter/server/lib/get_request.js new file mode 100644 index 0000000000000..2b29b05fd07aa --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/get_request.js @@ -0,0 +1,44 @@ +/* + * 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 boom from 'boom'; +import { API_ROUTE } from '../../common/constants'; + +export function getRequest(server, { headers }) { + const url = `${API_ROUTE}/ping`; + + return server + .inject({ + method: 'POST', + url, + headers, + }) + .then(res => { + if (res.statusCode !== 200) { + if (process.env.NODE_ENV !== 'production') { + console.error( + new Error(`Auth request failed: [${res.statusCode}] ${res.result.message}`) + ); + } + throw boom.unauthorized('Failed to authenticate socket connection'); + } + + return res.request; + }); +} diff --git a/x-pack/plugins/canvas/server/lib/route_expression/browser.js b/src/core_plugins/interpreter/server/lib/route_expression/browser.js similarity index 65% rename from x-pack/plugins/canvas/server/lib/route_expression/browser.js rename to src/core_plugins/interpreter/server/lib/route_expression/browser.js index feae107873ac6..0fe27f4d27c68 100644 --- a/x-pack/plugins/canvas/server/lib/route_expression/browser.js +++ b/src/core_plugins/interpreter/server/lib/route_expression/browser.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 uuid from 'uuid/v4'; diff --git a/x-pack/plugins/canvas/server/lib/route_expression/index.js b/src/core_plugins/interpreter/server/lib/route_expression/index.js similarity index 51% rename from x-pack/plugins/canvas/server/lib/route_expression/index.js rename to src/core_plugins/interpreter/server/lib/route_expression/index.js index 3533b55687246..1b3556e051d2d 100644 --- a/x-pack/plugins/canvas/server/lib/route_expression/index.js +++ b/src/core_plugins/interpreter/server/lib/route_expression/index.js @@ -1,9 +1,23 @@ /* - * 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. + * 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 { createError } from '../../../common/interpreter/create_error'; + +import { createError } from '@kbn/interpreter/common/interpreter/create_error'; export const routeExpressionProvider = environments => { async function routeExpression(ast, context = null) { diff --git a/src/core_plugins/interpreter/server/lib/route_expression/server.js b/src/core_plugins/interpreter/server/lib/route_expression/server.js new file mode 100644 index 0000000000000..50a80a1e0275a --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/route_expression/server.js @@ -0,0 +1,40 @@ +/* + * 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 { getServerRegistries } from '@kbn/interpreter/server/server_registries'; +import { interpretProvider } from '@kbn/interpreter/common/interpreter/interpret'; +import { createHandlers } from '../create_handlers'; + +export const server = async ({ onFunctionNotFound, server, request }) => { + const { serverFunctions, types } = await getServerRegistries(['serverFunctions', 'types']); + + return { + interpret: (ast, context) => { + const interpret = interpretProvider({ + types: types.toJS(), + functions: serverFunctions.toJS(), + handlers: createHandlers(request, server), + onFunctionNotFound, + }); + + return interpret(ast, context); + }, + getFunctions: () => Object.keys(serverFunctions.toJS()), + }; +}; diff --git a/src/core_plugins/interpreter/server/lib/route_expression/thread/babeled.js b/src/core_plugins/interpreter/server/lib/route_expression/thread/babeled.js new file mode 100644 index 0000000000000..2a19ef81d135e --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/route_expression/thread/babeled.js @@ -0,0 +1,32 @@ +/* + * 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. + */ + +require('babel-register')({ + ignore: [ + // stolen from kibana/src/setup_node_env/babel_register/register.js + // ignore paths matching `/node_modules/{a}/{b}`, unless `a` + // is `x-pack` and `b` is not `node_modules` + /\/node_modules\/(?!x-pack\/(?!node_modules)([^\/]+))([^\/]+\/[^\/]+)/, + ], + babelrc: false, + presets: [require.resolve('@kbn/babel-preset/node_preset')], +}); + +require('./polyfill'); +require('./worker'); diff --git a/x-pack/plugins/canvas/server/lib/route_expression/thread/index.js b/src/core_plugins/interpreter/server/lib/route_expression/thread/index.js similarity index 78% rename from x-pack/plugins/canvas/server/lib/route_expression/thread/index.js rename to src/core_plugins/interpreter/server/lib/route_expression/thread/index.js index d3748db02f65c..ff476793325e9 100644 --- a/x-pack/plugins/canvas/server/lib/route_expression/thread/index.js +++ b/src/core_plugins/interpreter/server/lib/route_expression/thread/index.js @@ -1,7 +1,20 @@ /* - * 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. + * 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 { fork } from 'child_process'; diff --git a/src/core_plugins/interpreter/server/lib/route_expression/thread/polyfill.js b/src/core_plugins/interpreter/server/lib/route_expression/thread/polyfill.js new file mode 100644 index 0000000000000..476777b4bc693 --- /dev/null +++ b/src/core_plugins/interpreter/server/lib/route_expression/thread/polyfill.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +// taken from kibana/src/setup_node_env/babel_register/polyfill.js +// ... +// `babel-preset-env` looks for and rewrites the following import +// statement into a list of import statements based on the polyfills +// necessary for our target environment (the current version of node) +// but since it does that during compilation, `import 'babel-polyfill'` +// must be in a file that is loaded with `require()` AFTER `babel-register` +// is configured. +// +// This is why we have this single statement in it's own file and require +// it from ./babeled.js +import 'babel-polyfill'; diff --git a/x-pack/plugins/canvas/server/lib/route_expression/thread/worker.js b/src/core_plugins/interpreter/server/lib/route_expression/thread/worker.js similarity index 62% rename from x-pack/plugins/canvas/server/lib/route_expression/thread/worker.js rename to src/core_plugins/interpreter/server/lib/route_expression/thread/worker.js index d81df410f7af7..5159679bb9f4f 100644 --- a/x-pack/plugins/canvas/server/lib/route_expression/thread/worker.js +++ b/src/core_plugins/interpreter/server/lib/route_expression/thread/worker.js @@ -1,13 +1,26 @@ /* - * 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. + * 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 uuid from 'uuid/v4'; -import { populateServerRegistries } from '../../server_registries'; -import { interpretProvider } from '../../../../common/interpreter/interpret'; -import { serializeProvider } from '../../../../common/lib/serialize'; +import { populateServerRegistries } from '@kbn/interpreter/server/server_registries'; +import { interpretProvider } from '@kbn/interpreter/common/interpreter/interpret'; +import { serializeProvider } from '@kbn/interpreter/common/lib/serialize'; // We actually DO need populateServerRegistries here since this is a different node process const pluginsReady = populateServerRegistries(['commonFunctions', 'types']); @@ -44,8 +57,9 @@ process.on('message', msg => { }, }); - if (type === 'getFunctions') + if (type === 'getFunctions') { process.send({ type: 'functionList', value: Object.keys(commonFunctions.toJS()) }); + } if (type === 'msgSuccess') { heap[id].resolve(deserialize(value)); diff --git a/src/core_plugins/interpreter/server/routes/index.js b/src/core_plugins/interpreter/server/routes/index.js new file mode 100644 index 0000000000000..f78baf4ad496d --- /dev/null +++ b/src/core_plugins/interpreter/server/routes/index.js @@ -0,0 +1,28 @@ +/* + * 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 { socketApi } from './socket'; +import { translate } from './translate'; +import { plugins } from './plugins'; + +export function routes(server) { + plugins(server); + socketApi(server); + translate(server); +} diff --git a/src/core_plugins/interpreter/server/routes/plugins.js b/src/core_plugins/interpreter/server/routes/plugins.js new file mode 100644 index 0000000000000..3d8c8614cc107 --- /dev/null +++ b/src/core_plugins/interpreter/server/routes/plugins.js @@ -0,0 +1,35 @@ +/* + * 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 { getPluginStream } from '../lib/get_plugin_stream'; + +export function plugins(server) { + server.route({ + method: 'GET', + path: '/api/canvas/plugins', + handler: function (request) { + const { type } = request.query; + + return getPluginStream(type); + }, + config: { + auth: false, + }, + }); +} diff --git a/x-pack/plugins/canvas/server/routes/socket.js b/src/core_plugins/interpreter/server/routes/socket.js similarity index 68% rename from x-pack/plugins/canvas/server/routes/socket.js rename to src/core_plugins/interpreter/server/routes/socket.js index 8e06c25769d4c..daf16ec7a4432 100644 --- a/x-pack/plugins/canvas/server/routes/socket.js +++ b/src/core_plugins/interpreter/server/routes/socket.js @@ -1,19 +1,32 @@ /* - * 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. + * 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 socket from 'socket.io'; -import { serializeProvider } from '../../common/lib/serialize'; -import { typesRegistry } from '../../common/lib/types_registry'; -import { getServerRegistries } from '../lib/server_registries'; -import { routeExpressionProvider } from '../lib/route_expression'; +import { serializeProvider } from '@kbn/interpreter/common/lib/serialize'; +import { typesRegistry } from '@kbn/interpreter/common/lib/types_registry'; +import { getServerRegistries } from '@kbn/interpreter/server/server_registries'; +import { routeExpressionProvider } from '../lib/route_expression/index'; import { browser } from '../lib/route_expression/browser'; -import { thread } from '../lib/route_expression/thread'; +import { thread } from '../lib/route_expression/thread/index'; import { server as serverEnv } from '../lib/route_expression/server'; import { getRequest } from '../lib/get_request'; -import { API_ROUTE } from '../../common/lib/constants'; +import { API_ROUTE } from '../../common/constants'; async function getModifiedRequest(server, socket) { try { diff --git a/src/core_plugins/interpreter/server/routes/translate.js b/src/core_plugins/interpreter/server/routes/translate.js new file mode 100644 index 0000000000000..865c0da3e0617 --- /dev/null +++ b/src/core_plugins/interpreter/server/routes/translate.js @@ -0,0 +1,48 @@ +/* + * 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 { fromExpression, toExpression } from '@kbn/interpreter/common/lib/ast'; + +export function translate(server) { + /* + Get AST from expression + */ + server.route({ + method: 'GET', + path: '/api/canvas/ast', + handler: function (request, h) { + if (!request.query.expression) { + return h.response({ error: '"expression" query is required' }).code(400); + } + return fromExpression(request.query.expression); + }, + }); + + server.route({ + method: 'POST', + path: '/api/canvas/expression', + handler: function (request, h) { + try { + return toExpression(request.payload); + } catch (e) { + return h.response({ error: e.message }).code(400); + } + }, + }); +} diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js index b0fe947f56920..1bf29fbac1d9d 100644 --- a/src/optimize/base_optimizer.js +++ b/src/optimize/base_optimizer.js @@ -150,8 +150,9 @@ export default class BaseOptimizer { }, { test, - include: /[\/\\]node_modules[\/\\]x-pack[\/\\]/, - exclude: /[\/\\]node_modules[\/\\]x-pack[\/\\](.+?[\/\\])*node_modules[\/\\]/, + include: /[\/\\]node_modules[\/\\](x-pack|@kbn[\/\\]interpreter)[\/\\]/, + exclude: /[\/\\]node_modules[\/\\](x-pack|@kbn[\/\\]interpreter)[\/\\]node_modules[\/\\]/, + } ]; }; diff --git a/src/setup_node_env/babel_register/register.js b/src/setup_node_env/babel_register/register.js index 2d909636a02a8..12690eab8f02c 100644 --- a/src/setup_node_env/babel_register/register.js +++ b/src/setup_node_env/babel_register/register.js @@ -39,7 +39,7 @@ var ignore = [ // ignore paths matching `/node_modules/{a}/{b}`, unless `a` // is `x-pack` and `b` is not `node_modules` - /\/node_modules\/(?!x-pack\/(?!node_modules)([^\/]+))([^\/]+\/[^\/]+)/ + /\/node_modules\/(?!(x-pack\/|@kbn\/interpreter\/)(?!node_modules)([^\/]+))([^\/]+\/[^\/]+)/ ]; if (global.__BUILT_WITH_BABEL__) { diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js index 34415cb6aeef5..1c8ade94456d0 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js @@ -201,4 +201,4 @@ describe('createOrUpgradeSavedConfig()', () => { '5.4.0-rc1': true, }); }); -}); \ No newline at end of file +}); diff --git a/x-pack/package.json b/x-pack/package.json index 02a59ea7ff3bc..ec99e4858af6b 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -126,6 +126,7 @@ "@kbn/datemath": "5.0.0", "@kbn/i18n": "1.0.0", "@kbn/ui-framework": "1.0.0", + "@kbn/interpreter": "1.0.0", "@samverschueren/stream-to-observable": "^0.3.0", "@scant/router": "^0.1.0", "@slack/client": "^4.2.2", diff --git a/x-pack/plugins/canvas/__tests__/fixtures/function_specs.js b/x-pack/plugins/canvas/__tests__/fixtures/function_specs.js index 433b5ec64b753..6ca97f159a1d5 100644 --- a/x-pack/plugins/canvas/__tests__/fixtures/function_specs.js +++ b/x-pack/plugins/canvas/__tests__/fixtures/function_specs.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Fn } from '../../common/lib/fn'; +import { Fn } from '@kbn/interpreter/common/lib/fn'; import { functions as browserFns } from '../../canvas_plugin_src/functions/browser'; import { functions as commonFns } from '../../canvas_plugin_src/functions/common'; import { functions as serverFns } from '../../canvas_plugin_src/functions/server/src'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.js index c85cc9e0d5baf..fcda50653380c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getType } from '../../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; export const asFn = () => ({ name: 'as', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clog.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clog.js deleted file mode 100644 index db4cc4179762f..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clog.js +++ /dev/null @@ -1,14 +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 const clog = () => ({ - name: 'clog', - help: 'Outputs the context to the console', - fn: context => { - console.log(context); //eslint-disable-line no-console - return context; - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.js index 410dbc60db952..f20c78bb1fa07 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.js @@ -11,7 +11,6 @@ import { asFn } from './as'; import { axisConfig } from './axisConfig'; import { compare } from './compare'; import { containerStyle } from './containerStyle'; -import { clog } from './clog'; import { context } from './context'; import { columns } from './columns'; import { csv } from './csv'; @@ -65,7 +64,6 @@ export const functions = [ any, asFn, axisConfig, - clog, columns, compare, containerStyle, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.js index db55780205296..c02c6a2d2691b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getType } from '../../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; export const mapColumn = () => ({ name: 'mapColumn', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.js index 1a8ee7daf7370..ce4b9170d1710 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.js @@ -5,7 +5,7 @@ */ import { get, map } from 'lodash'; -import { getType } from '../../../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; export const getFlotAxisConfig = (axis, argValue, { columns, ticks, font } = {}) => { if (!argValue || argValue.show === false) return { show: false }; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.js index 77580be49719a..b144cf179652d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getType } from '../../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; export const staticColumn = () => ({ name: 'staticColumn', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.js index 863fa41a90be5..04f92bc475256 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.js @@ -7,7 +7,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; import { get } from 'lodash'; -import { fromExpression, toExpression } from '../../../common/lib/ast'; +import { fromExpression, toExpression } from '@kbn/interpreter/common/lib/ast'; import { DropdownFilter } from './component'; export const dropdownFilter = () => ({ diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter/time_filter.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter/time_filter.js index d04a8f0b54d96..7ace73bc430d5 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter/time_filter.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter/time_filter.js @@ -7,7 +7,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { get } from 'lodash'; -import { fromExpression } from '../../../../../common/lib/ast'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; import { TimePicker } from '../time_picker'; import { TimePickerMini } from '../time_picker_mini'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.js index cdc4f563e1340..2ffc7bcf44208 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.js @@ -7,7 +7,7 @@ import ReactDOM from 'react-dom'; import React from 'react'; import { get, set } from 'lodash'; -import { fromExpression, toExpression } from '../../../common/lib/ast'; +import { fromExpression, toExpression } from '@kbn/interpreter/common/lib/ast'; import { TimeFilter } from './components/time_filter'; export const timeFilter = () => ({ diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/boolean.js b/x-pack/plugins/canvas/canvas_plugin_src/types/boolean.js deleted file mode 100644 index 697277a471fea..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/boolean.js +++ /dev/null @@ -1,29 +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 const boolean = () => ({ - name: 'boolean', - from: { - null: () => false, - number: n => Boolean(n), - string: s => Boolean(s), - }, - to: { - render: value => { - const text = `${value}`; - return { - type: 'render', - as: 'text', - value: { text }, - }; - }, - datatable: value => ({ - type: 'datatable', - columns: [{ name: 'value', type: 'boolean' }], - rows: [{ value }], - }), - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/error.js b/x-pack/plugins/canvas/canvas_plugin_src/types/error.js deleted file mode 100644 index 51051c804db56..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/error.js +++ /dev/null @@ -1,22 +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 const error = () => ({ - name: 'error', - to: { - render: input => { - const { error, info } = input; - return { - type: 'render', - as: 'error', - value: { - error, - info, - }, - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/filter.js b/x-pack/plugins/canvas/canvas_plugin_src/types/filter.js deleted file mode 100644 index 8627dd20bb89f..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/filter.js +++ /dev/null @@ -1,20 +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 const filter = () => ({ - name: 'filter', - from: { - null: () => { - return { - type: 'filter', - // Any meta data you wish to pass along. - meta: {}, - // And filters. If you need an "or", create a filter type for it. - and: [], - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/image.js b/x-pack/plugins/canvas/canvas_plugin_src/types/image.js deleted file mode 100644 index f63d3f1b8b2aa..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/image.js +++ /dev/null @@ -1,18 +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 const image = () => ({ - name: 'image', - to: { - render: input => { - return { - type: 'render', - as: 'image', - value: input, - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/index.js b/x-pack/plugins/canvas/canvas_plugin_src/types/index.js deleted file mode 100644 index 2e9a4fa02ef8e..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/index.js +++ /dev/null @@ -1,33 +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. - */ - -import { boolean } from './boolean'; -import { datatable } from './datatable'; -import { error } from './error'; -import { filter } from './filter'; -import { image } from './image'; -import { nullType } from './null'; -import { number } from './number'; -import { pointseries } from './pointseries'; -import { render } from './render'; -import { shape } from './shape'; -import { string } from './string'; -import { style } from './style'; - -export const typeSpecs = [ - boolean, - datatable, - error, - filter, - image, - number, - nullType, - pointseries, - render, - shape, - string, - style, -]; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/null.js b/x-pack/plugins/canvas/canvas_plugin_src/types/null.js deleted file mode 100644 index 27e9cdf59b004..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/null.js +++ /dev/null @@ -1,12 +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 const nullType = () => ({ - name: 'null', - from: { - '*': () => null, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/number.js b/x-pack/plugins/canvas/canvas_plugin_src/types/number.js deleted file mode 100644 index 63ee587075fdd..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/number.js +++ /dev/null @@ -1,29 +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 const number = () => ({ - name: 'number', - from: { - null: () => 0, - boolean: b => Number(b), - string: n => Number(n), - }, - to: { - render: value => { - const text = `${value}`; - return { - type: 'render', - as: 'text', - value: { text }, - }; - }, - datatable: value => ({ - type: 'datatable', - columns: [{ name: 'value', type: 'number' }], - rows: [{ value }], - }), - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/pointseries.js b/x-pack/plugins/canvas/canvas_plugin_src/types/pointseries.js deleted file mode 100644 index 1a00738620050..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/pointseries.js +++ /dev/null @@ -1,31 +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 const pointseries = () => ({ - name: 'pointseries', - from: { - null: () => { - return { - type: 'pointseries', - rows: [], - columns: [], - }; - }, - }, - to: { - render: (pointseries, types) => { - const datatable = types.datatable.from(pointseries, types); - return { - type: 'render', - as: 'table', - value: { - datatable, - showHeader: true, - }, - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/register.js b/x-pack/plugins/canvas/canvas_plugin_src/types/register.js deleted file mode 100644 index e960dd0f6566a..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/register.js +++ /dev/null @@ -1,10 +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. - */ - -import 'babel-polyfill'; -import { typeSpecs } from './index'; - -typeSpecs.forEach(canvas.register); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/render.js b/x-pack/plugins/canvas/canvas_plugin_src/types/render.js deleted file mode 100644 index 0f261f0398816..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/render.js +++ /dev/null @@ -1,16 +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 const render = () => ({ - name: 'render', - from: { - '*': v => ({ - type: 'render', - as: 'debug', - value: v, - }), - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/shape.js b/x-pack/plugins/canvas/canvas_plugin_src/types/shape.js deleted file mode 100644 index 1b306b7b1c391..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/shape.js +++ /dev/null @@ -1,18 +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 const shape = () => ({ - name: 'shape', - to: { - render: input => { - return { - type: 'render', - as: 'shape', - value: input, - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/string.js b/x-pack/plugins/canvas/canvas_plugin_src/types/string.js deleted file mode 100644 index c8d58aaaffbca..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/string.js +++ /dev/null @@ -1,28 +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 const string = () => ({ - name: 'string', - from: { - null: () => '', - boolean: b => String(b), - number: n => String(n), - }, - to: { - render: text => { - return { - type: 'render', - as: 'text', - value: { text }, - }; - }, - datatable: value => ({ - type: 'datatable', - columns: [{ name: 'value', type: 'string' }], - rows: [{ value }], - }), - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/types/style.js b/x-pack/plugins/canvas/canvas_plugin_src/types/style.js deleted file mode 100644 index 62632c03231ad..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/types/style.js +++ /dev/null @@ -1,18 +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 const style = () => ({ - name: 'style', - from: { - null: () => { - return { - type: 'style', - spec: {}, - css: '', - }; - }, - }, -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js index 0540a14603460..64a426a84a7cd 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js @@ -9,8 +9,8 @@ import { compose, withPropsOnChange, withHandlers } from 'recompose'; import PropTypes from 'prop-types'; import { EuiSelect, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { sortBy } from 'lodash'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; import { createStatefulPropHoc } from '../../../../public/components/enhance/stateful_prop'; -import { getType } from '../../../../common/lib/get_type'; import { templateFromReactComponent } from '../../../../public/lib/template_from_react_component'; import { SimpleMathFunction } from './simple_math_function'; import { getFormObject } from './get_form_object'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js index e0f8e56df8b6f..fc0f89692f646 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js @@ -7,8 +7,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { get } from 'lodash'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; import { PalettePicker } from '../../../public/components/palette_picker'; -import { getType } from '../../../common/lib/get_type'; import { templateFromReactComponent } from '../../../public/lib/template_from_react_component'; const PaletteArgInput = ({ onValueChange, argValue, renderError }) => { diff --git a/x-pack/plugins/canvas/common/functions/to.js b/x-pack/plugins/canvas/common/functions/to.js index 6f15569c27a11..25446b2868652 100644 --- a/x-pack/plugins/canvas/common/functions/to.js +++ b/x-pack/plugins/canvas/common/functions/to.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { castProvider } from '../interpreter/cast'; +import { castProvider } from '@kbn/interpreter/common/interpreter/cast'; export const to = () => ({ name: 'to', diff --git a/x-pack/plugins/canvas/common/interpreter/create_error.js b/x-pack/plugins/canvas/common/interpreter/create_error.js deleted file mode 100644 index 5de9819330dbd..0000000000000 --- a/x-pack/plugins/canvas/common/interpreter/create_error.js +++ /dev/null @@ -1,13 +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 const createError = err => ({ - type: 'error', - error: { - stack: process.env.NODE_ENV === 'production' ? undefined : err.stack, - message: typeof err === 'string' ? err : err.message, - }, -}); diff --git a/x-pack/plugins/canvas/common/lib/__tests__/arg.js b/x-pack/plugins/canvas/common/lib/__tests__/arg.js deleted file mode 100644 index f8badc67175ac..0000000000000 --- a/x-pack/plugins/canvas/common/lib/__tests__/arg.js +++ /dev/null @@ -1,23 +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. - */ - -import expect from 'expect.js'; -import { Arg } from '../arg'; - -describe('Arg', () => { - it('sets required to false by default', () => { - const isOptional = new Arg({ - name: 'optional_me', - }); - expect(isOptional.required).to.equal(false); - - const isRequired = new Arg({ - name: 'require_me', - required: true, - }); - expect(isRequired.required).to.equal(true); - }); -}); diff --git a/x-pack/plugins/canvas/common/lib/__tests__/get_by_alias.js b/x-pack/plugins/canvas/common/lib/__tests__/get_by_alias.js deleted file mode 100644 index eaeeeade4cc59..0000000000000 --- a/x-pack/plugins/canvas/common/lib/__tests__/get_by_alias.js +++ /dev/null @@ -1,74 +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. - */ - -import expect from 'expect.js'; -import { getByAlias } from '../get_by_alias'; - -describe('getByAlias', () => { - const fnsObject = { - foo: { name: 'foo', aliases: ['f'] }, - bar: { name: 'bar', aliases: ['b'] }, - }; - - const fnsArray = [{ name: 'foo', aliases: ['f'] }, { name: 'bar', aliases: ['b'] }]; - - it('returns the function by name', () => { - expect(getByAlias(fnsObject, 'foo')).to.be(fnsObject.foo); - expect(getByAlias(fnsObject, 'bar')).to.be(fnsObject.bar); - expect(getByAlias(fnsArray, 'foo')).to.be(fnsArray[0]); - expect(getByAlias(fnsArray, 'bar')).to.be(fnsArray[1]); - }); - - it('returns the function by alias', () => { - expect(getByAlias(fnsObject, 'f')).to.be(fnsObject.foo); - expect(getByAlias(fnsObject, 'b')).to.be(fnsObject.bar); - expect(getByAlias(fnsArray, 'f')).to.be(fnsArray[0]); - expect(getByAlias(fnsArray, 'b')).to.be(fnsArray[1]); - }); - - it('returns the function by case-insensitive name', () => { - expect(getByAlias(fnsObject, 'FOO')).to.be(fnsObject.foo); - expect(getByAlias(fnsObject, 'BAR')).to.be(fnsObject.bar); - expect(getByAlias(fnsArray, 'FOO')).to.be(fnsArray[0]); - expect(getByAlias(fnsArray, 'BAR')).to.be(fnsArray[1]); - }); - - it('returns the function by case-insensitive alias', () => { - expect(getByAlias(fnsObject, 'F')).to.be(fnsObject.foo); - expect(getByAlias(fnsObject, 'B')).to.be(fnsObject.bar); - expect(getByAlias(fnsArray, 'F')).to.be(fnsArray[0]); - expect(getByAlias(fnsArray, 'B')).to.be(fnsArray[1]); - }); - - it('handles empty strings', () => { - const emptyStringFnsObject = { '': { name: '' } }; - const emptyStringAliasFnsObject = { foo: { name: 'foo', aliases: [''] } }; - expect(getByAlias(emptyStringFnsObject, '')).to.be(emptyStringFnsObject['']); - expect(getByAlias(emptyStringAliasFnsObject, '')).to.be(emptyStringAliasFnsObject.foo); - - const emptyStringFnsArray = [{ name: '' }]; - const emptyStringAliasFnsArray = [{ name: 'foo', aliases: [''] }]; - expect(getByAlias(emptyStringFnsArray, '')).to.be(emptyStringFnsArray[0]); - expect(getByAlias(emptyStringAliasFnsArray, '')).to.be(emptyStringAliasFnsArray[0]); - }); - - it('handles "undefined" strings', () => { - const undefinedFnsObject = { undefined: { name: 'undefined' } }; - const undefinedAliasFnsObject = { foo: { name: 'undefined', aliases: ['undefined'] } }; - expect(getByAlias(undefinedFnsObject, 'undefined')).to.be(undefinedFnsObject.undefined); - expect(getByAlias(undefinedAliasFnsObject, 'undefined')).to.be(undefinedAliasFnsObject.foo); - - const emptyStringFnsArray = [{ name: 'undefined' }]; - const emptyStringAliasFnsArray = [{ name: 'foo', aliases: ['undefined'] }]; - expect(getByAlias(emptyStringFnsArray, 'undefined')).to.be(emptyStringFnsArray[0]); - expect(getByAlias(emptyStringAliasFnsArray, 'undefined')).to.be(emptyStringAliasFnsArray[0]); - }); - - it('returns undefined if not found', () => { - expect(getByAlias(fnsObject, 'baz')).to.be(undefined); - expect(getByAlias(fnsArray, 'baz')).to.be(undefined); - }); -}); diff --git a/x-pack/plugins/canvas/common/lib/arg.js b/x-pack/plugins/canvas/common/lib/arg.js deleted file mode 100644 index 7713fcb342bc2..0000000000000 --- a/x-pack/plugins/canvas/common/lib/arg.js +++ /dev/null @@ -1,24 +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. - */ - -import { includes } from 'lodash'; - -export function Arg(config) { - if (config.name === '_') throw Error('Arg names must not be _. Use it in aliases instead.'); - this.name = config.name; - this.required = config.required || false; - this.help = config.help || ''; - this.types = config.types || []; - this.default = config.default; - this.aliases = config.aliases || []; - this.multi = config.multi == null ? false : config.multi; - this.resolve = config.resolve == null ? true : config.resolve; - this.options = config.options || []; - this.accepts = type => { - if (!this.types.length) return true; - return includes(config.types, type); - }; -} diff --git a/x-pack/plugins/canvas/common/lib/autocomplete.js b/x-pack/plugins/canvas/common/lib/autocomplete.js index d87e199de4671..5a18c2570919b 100644 --- a/x-pack/plugins/canvas/common/lib/autocomplete.js +++ b/x-pack/plugins/canvas/common/lib/autocomplete.js @@ -5,8 +5,8 @@ */ import { uniq } from 'lodash'; -import { parse } from './grammar'; -import { getByAlias } from './get_by_alias'; +import { parse } from '@kbn/interpreter/common/lib/grammar'; +import { getByAlias } from '@kbn/interpreter/common/lib/get_by_alias'; const MARKER = 'CANVAS_SUGGESTION_MARKER'; diff --git a/x-pack/plugins/canvas/common/lib/functions_registry.js b/x-pack/plugins/canvas/common/lib/functions_registry.js deleted file mode 100644 index af8e8f0b122d0..0000000000000 --- a/x-pack/plugins/canvas/common/lib/functions_registry.js +++ /dev/null @@ -1,16 +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. - */ - -import { Registry } from '../../common/lib/registry'; -import { Fn } from '../lib/fn'; - -class FunctionsRegistry extends Registry { - wrapper(obj) { - return new Fn(obj); - } -} - -export const functionsRegistry = new FunctionsRegistry(); diff --git a/x-pack/plugins/canvas/common/lib/get_by_alias.js b/x-pack/plugins/canvas/common/lib/get_by_alias.js deleted file mode 100644 index c9986a5024008..0000000000000 --- a/x-pack/plugins/canvas/common/lib/get_by_alias.js +++ /dev/null @@ -1,20 +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. - */ - -/** - * This is used for looking up function/argument definitions. It looks through - * the given object/array for a case-insensitive match, which could be either the - * `name` itself, or something under the `aliases` property. - */ -export function getByAlias(specs, name) { - const lowerCaseName = name.toLowerCase(); - return Object.values(specs).find(({ name, aliases }) => { - if (name.toLowerCase() === lowerCaseName) return true; - return (aliases || []).some(alias => { - return alias.toLowerCase() === lowerCaseName; - }); - }); -} diff --git a/x-pack/plugins/canvas/common/lib/get_type.js b/x-pack/plugins/canvas/common/lib/get_type.js deleted file mode 100644 index 8d2b5a13cb283..0000000000000 --- a/x-pack/plugins/canvas/common/lib/get_type.js +++ /dev/null @@ -1,15 +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 function getType(node) { - if (node == null) return 'null'; - if (typeof node === 'object') { - if (!node.type) throw new Error('Objects must have a type propery'); - return node.type; - } - - return typeof node; -} diff --git a/x-pack/plugins/canvas/common/lib/index.js b/x-pack/plugins/canvas/common/lib/index.js index 5d56a5026590d..321a4abff44e0 100644 --- a/x-pack/plugins/canvas/common/lib/index.js +++ b/x-pack/plugins/canvas/common/lib/index.js @@ -5,8 +5,6 @@ */ export * from './datatable'; -export * from './arg'; -export * from './ast'; export * from './autocomplete'; export * from './constants'; export * from './dataurl'; @@ -14,15 +12,10 @@ export * from './errors'; export * from './expression_form_handlers'; export * from './fetch'; export * from './find_in_object'; -export * from './fn'; export * from './fonts'; -export * from './functions_registry'; -export * from './get_by_alias'; export * from './get_colors_from_palette'; export * from './get_field_type'; export * from './get_legend_config'; -export * from './get_type'; -export * from './grammar'; export * from './handlebars'; export * from './hex_to_rgb'; export * from './httpurl'; @@ -30,10 +23,6 @@ export * from './latest_change'; export * from './missing_asset'; export * from './palettes'; export * from './pivot_object_array'; -export * from './registry'; export * from './resolve_dataurl'; -export * from './serialize'; -export * from './type'; -export * from './types_registry'; export * from './unquote_string'; export * from './url'; diff --git a/x-pack/plugins/canvas/common/lib/serialize.js b/x-pack/plugins/canvas/common/lib/serialize.js deleted file mode 100644 index 0786f6f06b3a3..0000000000000 --- a/x-pack/plugins/canvas/common/lib/serialize.js +++ /dev/null @@ -1,24 +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. - */ - -import { get, identity } from 'lodash'; -import { getType } from '../lib/get_type'; - -export function serializeProvider(types) { - return { - serialize: provider('serialize'), - deserialize: provider('deserialize'), - }; - - function provider(key) { - return context => { - const type = getType(context); - const typeDef = types[type]; - const fn = get(typeDef, key) || identity; - return fn(context); - }; - } -} diff --git a/x-pack/plugins/canvas/common/lib/types_registry.js b/x-pack/plugins/canvas/common/lib/types_registry.js deleted file mode 100644 index 3d2bb65e9fa0f..0000000000000 --- a/x-pack/plugins/canvas/common/lib/types_registry.js +++ /dev/null @@ -1,16 +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. - */ - -import { Registry } from '../../common/lib/registry'; -import { Type } from '../../common/lib/type'; - -class TypesRegistry extends Registry { - wrapper(obj) { - return new Type(obj); - } -} - -export const typesRegistry = new TypesRegistry(); diff --git a/x-pack/plugins/canvas/index.js b/x-pack/plugins/canvas/index.js index b92e29341a14b..0f34eef6c2edb 100644 --- a/x-pack/plugins/canvas/index.js +++ b/x-pack/plugins/canvas/index.js @@ -5,9 +5,11 @@ */ import { resolve } from 'path'; +import { pathsRegistry } from '@kbn/interpreter/common/lib/paths_registry'; import init from './init'; import { mappings } from './server/mappings'; import { CANVAS_APP } from './common/lib/constants'; +import { pluginPaths } from './plugin_paths'; export function canvas(kibana) { return new kibana.Plugin({ @@ -39,6 +41,9 @@ export function canvas(kibana) { }).default(); }, + preInit: () => { + pathsRegistry.registerAll(pluginPaths); + }, init, }); } diff --git a/x-pack/plugins/canvas/init.js b/x-pack/plugins/canvas/init.js index 1ef56fac4e97c..70a8db10d7e66 100644 --- a/x-pack/plugins/canvas/init.js +++ b/x-pack/plugins/canvas/init.js @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import { functionsRegistry } from '@kbn/interpreter/common/lib/functions_registry'; +import { getServerRegistries } from '@kbn/interpreter/server/server_registries'; import { routes } from './server/routes'; -import { functionsRegistry } from './common/lib'; import { commonFunctions } from './common/functions'; -import { populateServerRegistries } from './server/lib/server_registries'; import { registerCanvasUsageCollector } from './server/usage'; import { loadSampleData } from './server/sample_data'; @@ -34,6 +34,6 @@ export default async function(server /*options*/) { loadSampleData(server); // Do not initialize the app until the registries are populated - await populateServerRegistries(['serverFunctions', 'types']); + await getServerRegistries(); routes(server); } diff --git a/x-pack/plugins/canvas/plugin_paths.js b/x-pack/plugins/canvas/plugin_paths.js new file mode 100644 index 0000000000000..9c9f5d1c49bde --- /dev/null +++ b/x-pack/plugins/canvas/plugin_paths.js @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { resolve } from 'path'; + +export const pluginPaths = { + serverFunctions: resolve(__dirname, 'canvas_plugin/functions/server'), + browserFunctions: resolve(__dirname, 'canvas_plugin/functions/browser'), + commonFunctions: resolve(__dirname, 'canvas_plugin/functions/common'), + elements: resolve(__dirname, 'canvas_plugin/elements'), + renderers: resolve(__dirname, 'canvas_plugin/renderers'), + interfaces: resolve(__dirname, 'canvas_plugin/interfaces'), + transformUIs: resolve(__dirname, 'canvas_plugin/uis/transforms'), + datasourceUIs: resolve(__dirname, 'canvas_plugin/uis/datasources'), + modelUIs: resolve(__dirname, 'canvas_plugin/uis/models'), + viewUIs: resolve(__dirname, 'canvas_plugin/uis/views'), + argumentUIs: resolve(__dirname, 'canvas_plugin/uis/arguments'), +}; diff --git a/x-pack/plugins/canvas/public/components/app/index.js b/x-pack/plugins/canvas/public/components/app/index.js index 5f633169604d6..b776bf59efc99 100644 --- a/x-pack/plugins/canvas/public/components/app/index.js +++ b/x-pack/plugins/canvas/public/components/app/index.js @@ -4,15 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ +import { createSocket } from '@kbn/interpreter/public/socket'; +import { initialize as initializeInterpreter } from '@kbn/interpreter/public/interpreter'; import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; -import { createSocket } from '../../socket'; -import { initialize as initializeInterpreter } from '../../lib/interpreter'; -import { populateBrowserRegistries } from '../../lib/browser_registries'; +import { populateBrowserRegistries } from '@kbn/interpreter/public/browser_registries'; import { getAppReady, getBasePath } from '../../state/selectors/app'; import { appReady, appError } from '../../state/actions/app'; -import { trackRouteChange } from './track_route_change'; +import { loadPrivateBrowserFunctions } from '../../lib/load_private_browser_functions'; +import { elementsRegistry } from '../../lib/elements_registry'; +import { renderFunctionsRegistry } from '../../lib/render_functions_registry'; +import { + argTypeRegistry, + datasourceRegistry, + modelRegistry, + transformRegistry, + viewRegistry, +} from '../../expression_types'; import { App as Component } from './app'; +import { trackRouteChange } from './track_route_change'; const mapStateToProps = state => { // appReady could be an error object @@ -24,13 +34,24 @@ const mapStateToProps = state => { }; }; +const types = { + elements: elementsRegistry, + renderers: renderFunctionsRegistry, + transformUIs: transformRegistry, + datasourceUIs: datasourceRegistry, + modelUIs: modelRegistry, + viewUIs: viewRegistry, + argumentUIs: argTypeRegistry, +}; + const mapDispatchToProps = dispatch => ({ // TODO: the correct socket path should come from upstream, using the constant here is not ideal setAppReady: basePath => async () => { try { // initialize the socket and interpreter await createSocket(basePath); - await populateBrowserRegistries(); + loadPrivateBrowserFunctions(); + await populateBrowserRegistries(types); await initializeInterpreter(); // set app state to ready diff --git a/x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js b/x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js index 2bd779de759d9..13ecfe89bb922 100644 --- a/x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js +++ b/x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js @@ -8,8 +8,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { compose, withProps, withPropsOnChange } from 'recompose'; import { EuiForm, EuiTextArea, EuiButton, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; +import { fromExpression, toExpression } from '@kbn/interpreter/common/lib/ast'; import { createStatefulPropHoc } from '../../components/enhance/stateful_prop'; -import { fromExpression, toExpression } from '../../../common/lib/ast'; export const AdvancedFailureComponent = props => { const { 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 8b21c38a5f6f7..f1f3fb2ddae97 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,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import { interpretAst } from '@kbn/interpreter/public/interpreter'; import { pure, compose, lifecycle, withState, branch, renderComponent } from 'recompose'; import { PropTypes } from 'prop-types'; import { Loading } from '../../loading'; -import { interpretAst } from '../../../lib/interpreter'; import { DatasourcePreview as Component } from './datasource_preview'; export const DatasourcePreview = compose( diff --git a/x-pack/plugins/canvas/public/components/element_content/element_content.js b/x-pack/plugins/canvas/public/components/element_content/element_content.js index 4a62f219b2ba5..40cca930827db 100644 --- a/x-pack/plugins/canvas/public/components/element_content/element_content.js +++ b/x-pack/plugins/canvas/public/components/element_content/element_content.js @@ -8,7 +8,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { pure, compose, branch, renderComponent } from 'recompose'; import Style from 'style-it'; -import { getType } from '../../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; import { Loading } from '../loading'; import { RenderWithFn } from '../render_with_fn'; import { ElementShareContainer } from '../element_share_container'; diff --git a/x-pack/plugins/canvas/public/components/expression/index.js b/x-pack/plugins/canvas/public/components/expression/index.js index 18690529d4e80..81d73959e83b8 100644 --- a/x-pack/plugins/canvas/public/components/expression/index.js +++ b/x-pack/plugins/canvas/public/components/expression/index.js @@ -15,9 +15,9 @@ import { branch, renderComponent, } from 'recompose'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; import { getSelectedPage, getSelectedElement } from '../../state/selectors/workpad'; import { setExpression, flushContext } from '../../state/actions/elements'; -import { fromExpression } from '../../../common/lib/ast'; import { getFunctionDefinitions } from '../../lib/function_definitions'; import { getWindow } from '../../lib/get_window'; import { ElementNotSelected } from './element_not_selected'; 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 8b6702d94340f..84748f5bbbbb3 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,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { interpretAst } from '@kbn/interpreter/public/interpreter'; import { compose, withProps } from 'recompose'; import { get } from 'lodash'; +import { toExpression } from '@kbn/interpreter/common/lib/ast'; import { modelRegistry, viewRegistry, transformRegistry } from '../../expression_types'; -import { interpretAst } from '../../lib/interpreter'; -import { toExpression } from '../../../common/lib/ast'; import { FunctionFormList as Component } from './function_form_list'; function normalizeContext(chain) { diff --git a/x-pack/plugins/canvas/public/expression_types/arg_type.js b/x-pack/plugins/canvas/public/expression_types/arg_type.js index 76f29afee7185..a19c726e138c2 100644 --- a/x-pack/plugins/canvas/public/expression_types/arg_type.js +++ b/x-pack/plugins/canvas/public/expression_types/arg_type.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { BaseForm } from './base_form'; export class ArgType extends BaseForm { diff --git a/x-pack/plugins/canvas/public/expression_types/datasource.js b/x-pack/plugins/canvas/public/expression_types/datasource.js index 858be2b4e33dd..cd9a8af5f0182 100644 --- a/x-pack/plugins/canvas/public/expression_types/datasource.js +++ b/x-pack/plugins/canvas/public/expression_types/datasource.js @@ -6,7 +6,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { RenderToDom } from '../components/render_to_dom'; import { ExpressionFormHandlers } from '../../common/lib/expression_form_handlers'; import { BaseForm } from './base_form'; diff --git a/x-pack/plugins/canvas/public/expression_types/function_form.js b/x-pack/plugins/canvas/public/expression_types/function_form.js index 70da0004ab175..c7bc16a5b2e2b 100644 --- a/x-pack/plugins/canvas/public/expression_types/function_form.js +++ b/x-pack/plugins/canvas/public/expression_types/function_form.js @@ -7,7 +7,7 @@ import { EuiCallOut } from '@elastic/eui'; import React from 'react'; import { isPlainObject, uniq, last, compact } from 'lodash'; -import { fromExpression } from '../../common/lib/ast'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; import { ArgAddPopover } from '../components/arg_add_popover'; import { SidebarSection } from '../components/sidebar/sidebar_section'; import { SidebarSectionTitle } from '../components/sidebar/sidebar_section_title'; diff --git a/x-pack/plugins/canvas/public/expression_types/model.js b/x-pack/plugins/canvas/public/expression_types/model.js index bae74d75589be..7ce1126bdec55 100644 --- a/x-pack/plugins/canvas/public/expression_types/model.js +++ b/x-pack/plugins/canvas/public/expression_types/model.js @@ -5,7 +5,7 @@ */ import { get, pick } from 'lodash'; -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { FunctionForm } from './function_form'; const NO_NEXT_EXP = 'no next expression'; diff --git a/x-pack/plugins/canvas/public/expression_types/transform.js b/x-pack/plugins/canvas/public/expression_types/transform.js index 216e79b9c106c..760eae46195d6 100644 --- a/x-pack/plugins/canvas/public/expression_types/transform.js +++ b/x-pack/plugins/canvas/public/expression_types/transform.js @@ -5,7 +5,7 @@ */ import { pick } from 'lodash'; -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { FunctionForm } from './function_form'; export class Transform extends FunctionForm { diff --git a/x-pack/plugins/canvas/public/expression_types/view.js b/x-pack/plugins/canvas/public/expression_types/view.js index ee83fe3340d76..1b7fe13d508b0 100644 --- a/x-pack/plugins/canvas/public/expression_types/view.js +++ b/x-pack/plugins/canvas/public/expression_types/view.js @@ -5,7 +5,7 @@ */ import { pick } from 'lodash'; -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { FunctionForm } from './function_form'; export class View extends FunctionForm { diff --git a/x-pack/plugins/canvas/public/functions/filters.js b/x-pack/plugins/canvas/public/functions/filters.js index a6f8d2a63fc5e..3c578a93fc3b6 100644 --- a/x-pack/plugins/canvas/public/functions/filters.js +++ b/x-pack/plugins/canvas/public/functions/filters.js @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fromExpression } from '../../common/lib/ast'; -import { typesRegistry } from '../../common/lib/types_registry'; +import { interpretAst } from '@kbn/interpreter/public/interpreter'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; +import { typesRegistry } from '@kbn/interpreter/common/lib/types_registry'; import { getState } from '../state/store'; import { getGlobalFilterExpression } from '../state/selectors/workpad'; -import { interpretAst } from '../lib/interpreter'; export const filters = () => ({ name: 'filters', diff --git a/x-pack/plugins/canvas/public/lib/arg_helpers.js b/x-pack/plugins/canvas/public/lib/arg_helpers.js index e53e26b62dd15..e1cd8b64b323f 100644 --- a/x-pack/plugins/canvas/public/lib/arg_helpers.js +++ b/x-pack/plugins/canvas/public/lib/arg_helpers.js @@ -5,7 +5,7 @@ */ import { includes } from 'lodash'; -import { getType } from '../../common/lib/get_type'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; /* diff --git a/x-pack/plugins/canvas/public/lib/browser_registries.js b/x-pack/plugins/canvas/public/lib/browser_registries.js deleted file mode 100644 index efceec04d6dce..0000000000000 --- a/x-pack/plugins/canvas/public/lib/browser_registries.js +++ /dev/null @@ -1,74 +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. - */ - -import chrome from 'ui/chrome'; -import $script from 'scriptjs'; -import { typesRegistry } from '../../common/lib/types_registry'; -import { - argTypeRegistry, - datasourceRegistry, - transformRegistry, - modelRegistry, - viewRegistry, -} from '../expression_types'; -import { elementsRegistry } from './elements_registry'; -import { renderFunctionsRegistry } from './render_functions_registry'; -import { functionsRegistry as browserFunctions } from './functions_registry'; -import { loadPrivateBrowserFunctions } from './load_private_browser_functions'; - -const registries = { - browserFunctions: browserFunctions, - commonFunctions: browserFunctions, - elements: elementsRegistry, - types: typesRegistry, - renderers: renderFunctionsRegistry, - transformUIs: transformRegistry, - datasourceUIs: datasourceRegistry, - modelUIs: modelRegistry, - viewUIs: viewRegistry, - argumentUIs: argTypeRegistry, -}; - -let resolve = null; -let called = false; - -const populatePromise = new Promise(_resolve => { - resolve = _resolve; -}); - -export const getBrowserRegistries = () => { - return populatePromise; -}; - -export const populateBrowserRegistries = () => { - if (called) throw new Error('function should only be called once per process'); - called = true; - - // loadPrivateBrowserFunctions is sync. No biggie. - loadPrivateBrowserFunctions(); - - const remainingTypes = Object.keys(registries); - const populatedTypes = {}; - - function loadType() { - const type = remainingTypes.pop(); - window.canvas = window.canvas || {}; - window.canvas.register = d => registries[type].register(d); - - // Load plugins one at a time because each needs a different loader function - // $script will only load each of these once, we so can call this as many times as we need? - const pluginPath = chrome.addBasePath(`/api/canvas/plugins?type=${type}`); - $script(pluginPath, () => { - populatedTypes[type] = registries[type]; - - if (remainingTypes.length) loadType(); - else resolve(populatedTypes); - }); - } - - if (remainingTypes.length) loadType(); - return populatePromise; -}; diff --git a/x-pack/plugins/canvas/public/lib/create_handlers.js b/x-pack/plugins/canvas/public/lib/create_handlers.js deleted file mode 100644 index 93247210eb291..0000000000000 --- a/x-pack/plugins/canvas/public/lib/create_handlers.js +++ /dev/null @@ -1,11 +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 function createHandlers(/*socket*/) { - return { - environment: 'client', - }; -} diff --git a/x-pack/plugins/canvas/public/lib/elements_registry.js b/x-pack/plugins/canvas/public/lib/elements_registry.js index 898fba183c9f5..dc3d743f49877 100644 --- a/x-pack/plugins/canvas/public/lib/elements_registry.js +++ b/x-pack/plugins/canvas/public/lib/elements_registry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { Element } from './element'; class ElementsRegistry extends Registry { diff --git a/x-pack/plugins/canvas/public/lib/function_definitions.js b/x-pack/plugins/canvas/public/lib/function_definitions.js index c4bc16a4c94c3..c0f3496dfc083 100644 --- a/x-pack/plugins/canvas/public/lib/function_definitions.js +++ b/x-pack/plugins/canvas/public/lib/function_definitions.js @@ -5,8 +5,8 @@ */ import uniqBy from 'lodash.uniqby'; +import { getBrowserRegistries } from '@kbn/interpreter/public/browser_registries'; import { getServerFunctions } from '../state/selectors/app'; -import { getBrowserRegistries } from './browser_registries'; export async function getFunctionDefinitions(state) { const { browserFunctions } = await getBrowserRegistries(); diff --git a/x-pack/plugins/canvas/public/lib/functions_registry.js b/x-pack/plugins/canvas/public/lib/functions_registry.js index 3cc084d8ca66e..36f9a631f06ea 100644 --- a/x-pack/plugins/canvas/public/lib/functions_registry.js +++ b/x-pack/plugins/canvas/public/lib/functions_registry.js @@ -5,4 +5,4 @@ */ // export the common registry here, so it's available in plugin public code -export { functionsRegistry } from '../../common/lib/functions_registry'; +export { functionsRegistry } from '@kbn/interpreter/common/lib/functions_registry'; diff --git a/x-pack/plugins/canvas/public/lib/parse_single_function_chain.js b/x-pack/plugins/canvas/public/lib/parse_single_function_chain.js index f8eec880af624..696c058e34a2b 100644 --- a/x-pack/plugins/canvas/public/lib/parse_single_function_chain.js +++ b/x-pack/plugins/canvas/public/lib/parse_single_function_chain.js @@ -5,7 +5,7 @@ */ import { get, mapValues, map } from 'lodash'; -import { fromExpression } from '../../common/lib/ast'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; export function parseSingleFunctionChain(filterString) { const ast = fromExpression(filterString); diff --git a/x-pack/plugins/canvas/public/lib/render_functions_registry.js b/x-pack/plugins/canvas/public/lib/render_functions_registry.js index 3d040047aeb9a..a34ed009a33b1 100644 --- a/x-pack/plugins/canvas/public/lib/render_functions_registry.js +++ b/x-pack/plugins/canvas/public/lib/render_functions_registry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { RenderFunction } from './render_function'; class RenderFunctionsRegistry extends Registry { diff --git a/x-pack/plugins/canvas/public/lib/run_interpreter.js b/x-pack/plugins/canvas/public/lib/run_interpreter.js index cc0d9a7544786..7bb898b254ec8 100644 --- a/x-pack/plugins/canvas/public/lib/run_interpreter.js +++ b/x-pack/plugins/canvas/public/lib/run_interpreter.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fromExpression } from '../../common/lib/ast'; -import { getType } from '../../common/lib/get_type'; -import { interpretAst } from './interpreter'; +import { interpretAst } from '@kbn/interpreter/public/interpreter'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; +import { getType } from '@kbn/interpreter/common/lib/get_type'; import { notify } from './notify'; /** diff --git a/x-pack/plugins/canvas/public/lib/transitions_registry.js b/x-pack/plugins/canvas/public/lib/transitions_registry.js index 8d2e421b8233c..8ead0aa896ab7 100644 --- a/x-pack/plugins/canvas/public/lib/transitions_registry.js +++ b/x-pack/plugins/canvas/public/lib/transitions_registry.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Registry } from '../../common/lib/registry'; +import { Registry } from '@kbn/interpreter/common/lib/registry'; import { Transition } from '../transitions/transition'; class TransitionsRegistry extends Registry { diff --git a/x-pack/plugins/canvas/public/lib/types_registry.js b/x-pack/plugins/canvas/public/lib/types_registry.js index c1f13b1ae4612..05b82c744c383 100644 --- a/x-pack/plugins/canvas/public/lib/types_registry.js +++ b/x-pack/plugins/canvas/public/lib/types_registry.js @@ -5,4 +5,4 @@ */ // export the common registry here, so it's available in plugin public code -export { typesRegistry } from '../../common/lib/types_registry'; +export { typesRegistry } from '@kbn/interpreter/common/lib/types_registry'; diff --git a/x-pack/plugins/canvas/public/state/actions/elements.js b/x-pack/plugins/canvas/public/state/actions/elements.js index fb82de32fc0ef..be157d9d8085b 100644 --- a/x-pack/plugins/canvas/public/state/actions/elements.js +++ b/x-pack/plugins/canvas/public/state/actions/elements.js @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ +import { interpretAst } from '@kbn/interpreter/public/interpreter'; import { createAction } from 'redux-actions'; import { createThunk } from 'redux-thunks'; import { set, del } from 'object-path-immutable'; import { get, pick, cloneDeep, without } from 'lodash'; +import { toExpression, safeElementFromExpression } from '@kbn/interpreter/common/lib/ast'; import { getPages, getElementById, getSelectedPageIndex } from '../selectors/workpad'; import { getValue as getResolvedArgsValue } from '../selectors/resolved_args'; import { getDefaultElement } from '../defaults'; -import { toExpression, safeElementFromExpression } from '../../../common/lib/ast'; import { notify } from '../../lib/notify'; import { runInterpreter } from '../../lib/run_interpreter'; -import { interpretAst } from '../../lib/interpreter'; import { selectElement } from './transient'; import * as args from './resolved_args'; diff --git a/x-pack/plugins/canvas/public/state/selectors/workpad.js b/x-pack/plugins/canvas/public/state/selectors/workpad.js index 1db0128abab07..6d888f60c2191 100644 --- a/x-pack/plugins/canvas/public/state/selectors/workpad.js +++ b/x-pack/plugins/canvas/public/state/selectors/workpad.js @@ -5,7 +5,7 @@ */ import { get, omit } from 'lodash'; -import { safeElementFromExpression } from '../../../common/lib/ast'; +import { safeElementFromExpression } from '@kbn/interpreter/common/lib/ast'; import { append } from '../../lib/modify_path'; import { getAssets } from './assets'; diff --git a/x-pack/plugins/canvas/server/lib/feature_check.js b/x-pack/plugins/canvas/server/lib/feature_check.js deleted file mode 100644 index e9cec02923582..0000000000000 --- a/x-pack/plugins/canvas/server/lib/feature_check.js +++ /dev/null @@ -1,13 +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. - */ - -// TODO: replace this when we use the method exposed by security https://github.com/elastic/kibana/pull/24616 -export const isSecurityEnabled = server => { - const kibanaSecurity = server.plugins.security; - const esSecurity = server.plugins.xpack_main.info.feature('security'); - - return kibanaSecurity && esSecurity.isAvailable() && esSecurity.isEnabled(); -}; diff --git a/x-pack/plugins/canvas/server/lib/get_plugin_paths.js b/x-pack/plugins/canvas/server/lib/get_plugin_paths.js deleted file mode 100644 index 02582e5f749cc..0000000000000 --- a/x-pack/plugins/canvas/server/lib/get_plugin_paths.js +++ /dev/null @@ -1,83 +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. - */ - -import path from 'path'; -import fs from 'fs'; -import { promisify } from 'util'; -import { flatten } from 'lodash'; -import { pluginPaths } from './plugin_paths'; - -const lstat = promisify(fs.lstat); -const readdir = promisify(fs.readdir); - -const canvasPluginDirectoryName = 'canvas_plugin'; - -const isDirectory = path => - lstat(path) - .then(stat => stat.isDirectory()) - .catch(() => false); - -const isDirname = (p, name) => path.basename(p) === name; - -const getKibanaPluginsPath = () => { - const basePluginPath = path.resolve(__dirname, '..', '..', '..', '..', '..'); - - // find the kibana path in dev mode - if (isDirname(basePluginPath, 'kibana')) return path.join(basePluginPath, 'plugins'); - - // find the kibana path in the build, which lives in node_modules and requires going 1 path up - const buildPluginPath = path.join(basePluginPath, '..'); - if (isDirname(basePluginPath, 'node_modules')) { - const pluginPath = path.join(buildPluginPath, 'plugins'); - return isDirectory(pluginPath) && pluginPath; - } - - return false; -}; - -// These must all exist -const paths = [ - path.resolve(__dirname, '..', '..', '..'), // Canvas core plugins - getKibanaPluginsPath(), // Kibana plugin directory -].filter(Boolean); - -export const getPluginPaths = type => { - const typePath = pluginPaths[type]; - if (!typePath) throw new Error(`Unknown type: ${type}`); - - async function findPlugins(directory) { - const isDir = await isDirectory(directory); - if (!isDir) return; - - const names = await readdir(directory); // Get names of everything in the directory - return names - .filter(name => name[0] !== '.') - .map(name => path.resolve(directory, name, canvasPluginDirectoryName, ...typePath)); - } - - return Promise.all(paths.map(findPlugins)) - .then(dirs => - dirs.reduce((list, dir) => { - if (!dir) return list; - return list.concat(dir); - }, []) - ) - .then(possibleCanvasPlugins => { - // Check how many are directories. If lstat fails it doesn't exist anyway. - return Promise.all( - // An array - possibleCanvasPlugins.map(pluginPath => isDirectory(pluginPath)) - ).then(isDirectory => possibleCanvasPlugins.filter((pluginPath, i) => isDirectory[i])); - }) - .then(canvasPluginDirectories => { - return Promise.all( - canvasPluginDirectories.map(dir => - // Get the full path of all files in the directory - readdir(dir).then(files => files.map(file => path.resolve(dir, file))) - ) - ).then(flatten); - }); -}; diff --git a/x-pack/plugins/canvas/server/lib/get_plugin_stream.js b/x-pack/plugins/canvas/server/lib/get_plugin_stream.js deleted file mode 100644 index 6a08e2beeff8e..0000000000000 --- a/x-pack/plugins/canvas/server/lib/get_plugin_stream.js +++ /dev/null @@ -1,24 +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. - */ - -import fs from 'fs'; -import ss from 'stream-stream'; -import { getPluginPaths } from './get_plugin_paths'; - -export const getPluginStream = type => { - const stream = ss({ - separator: '\n', - }); - - getPluginPaths(type).then(files => { - files.forEach(file => { - stream.write(fs.createReadStream(file)); - }); - stream.end(); - }); - - return stream; -}; diff --git a/x-pack/plugins/canvas/server/lib/get_request.js b/x-pack/plugins/canvas/server/lib/get_request.js deleted file mode 100644 index d55421e437fc4..0000000000000 --- a/x-pack/plugins/canvas/server/lib/get_request.js +++ /dev/null @@ -1,30 +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. - */ -import boom from 'boom'; -import { API_ROUTE } from '../../common/lib/constants'; - -export function getRequest(server, { headers }) { - const url = `${API_ROUTE}/ping`; - - return server - .inject({ - method: 'POST', - url, - headers, - }) - .then(res => { - if (res.statusCode !== 200) { - if (process.env.NODE_ENV !== 'production') { - console.error( - new Error(`Auth request failed: [${res.statusCode}] ${res.result.message}`) - ); - } - throw boom.unauthorized('Failed to authenticate socket connection'); - } - - return res.request; - }); -} diff --git a/x-pack/plugins/canvas/server/lib/plugin_paths.js b/x-pack/plugins/canvas/server/lib/plugin_paths.js deleted file mode 100644 index cb90cc0c0f06c..0000000000000 --- a/x-pack/plugins/canvas/server/lib/plugin_paths.js +++ /dev/null @@ -1,20 +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 const pluginPaths = { - serverFunctions: ['functions', 'server'], - browserFunctions: ['functions', 'browser'], - commonFunctions: ['functions', 'common'], - types: ['types'], - elements: ['elements'], - renderers: ['renderers'], - interfaces: ['interfaces'], - transformUIs: ['uis', 'transforms'], - datasourceUIs: ['uis', 'datasources'], - modelUIs: ['uis', 'models'], - viewUIs: ['uis', 'views'], - argumentUIs: ['uis', 'arguments'], -}; diff --git a/x-pack/plugins/canvas/server/lib/route_expression/server.js b/x-pack/plugins/canvas/server/lib/route_expression/server.js deleted file mode 100644 index b24e4cb7e5e41..0000000000000 --- a/x-pack/plugins/canvas/server/lib/route_expression/server.js +++ /dev/null @@ -1,27 +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. - */ - -import { getServerRegistries } from '../server_registries'; -import { interpretProvider } from '../../../common/interpreter/interpret'; -import { createHandlers } from '../create_handlers'; - -export const server = async ({ onFunctionNotFound, server, request }) => { - const { serverFunctions, types } = await getServerRegistries(['serverFunctions', 'types']); - - return { - interpret: (ast, context) => { - const interpret = interpretProvider({ - types: types.toJS(), - functions: serverFunctions.toJS(), - handlers: createHandlers(request, server), - onFunctionNotFound, - }); - - return interpret(ast, context); - }, - getFunctions: () => Object.keys(serverFunctions.toJS()), - }; -}; diff --git a/x-pack/plugins/canvas/server/lib/route_expression/thread/babeled.js b/x-pack/plugins/canvas/server/lib/route_expression/thread/babeled.js deleted file mode 100644 index b7c1e83beb7c7..0000000000000 --- a/x-pack/plugins/canvas/server/lib/route_expression/thread/babeled.js +++ /dev/null @@ -1,19 +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. - */ - -require('babel-register')({ - ignore: [ - // stolen from kibana/src/setup_node_env/babel_register/register.js - // ignore paths matching `/node_modules/{a}/{b}`, unless `a` - // is `x-pack` and `b` is not `node_modules` - /\/node_modules\/(?!x-pack\/(?!node_modules)([^\/]+))([^\/]+\/[^\/]+)/, - ], - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/node_preset')], -}); - -require('./polyfill'); -require('./worker'); diff --git a/x-pack/plugins/canvas/server/lib/route_expression/thread/polyfill.js b/x-pack/plugins/canvas/server/lib/route_expression/thread/polyfill.js deleted file mode 100644 index be4983e9a37e8..0000000000000 --- a/x-pack/plugins/canvas/server/lib/route_expression/thread/polyfill.js +++ /dev/null @@ -1,18 +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. - */ - -// taken from kibana/src/setup_node_env/babel_register/polyfill.js -// ... -// `babel-preset-env` looks for and rewrites the following import -// statement into a list of import statements based on the polyfills -// necessary for our target environment (the current version of node) -// but since it does that during compilation, `import 'babel-polyfill'` -// must be in a file that is loaded with `require()` AFTER `babel-register` -// is configured. -// -// This is why we have this single statement in it's own file and require -// it from ./babeled.js -import 'babel-polyfill'; diff --git a/x-pack/plugins/canvas/server/lib/server_registries.js b/x-pack/plugins/canvas/server/lib/server_registries.js deleted file mode 100644 index cff63a1138ea3..0000000000000 --- a/x-pack/plugins/canvas/server/lib/server_registries.js +++ /dev/null @@ -1,55 +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. - */ - -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; - -const populatePromise = new Promise(_resolve => { - resolve = _resolve; -}); - -export const getServerRegistries = () => { - return populatePromise; -}; - -export const populateServerRegistries = types => { - if (called) throw new Error('function should only be called once per process'); - called = true; - if (!types || !types.length) throw new Error('types is required'); - - const remainingTypes = types; - const populatedTypes = {}; - - 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); - }); - - global.canvas = undefined; - populatedTypes[type] = registries[type]; - if (remainingTypes.length) loadType(); - else resolve(populatedTypes); - }); - }; - - if (remainingTypes.length) loadType(); - return populatePromise; -}; diff --git a/x-pack/plugins/canvas/server/routes/index.js b/x-pack/plugins/canvas/server/routes/index.js index ab2edfe86b56f..45f26a423fc84 100644 --- a/x-pack/plugins/canvas/server/routes/index.js +++ b/x-pack/plugins/canvas/server/routes/index.js @@ -5,15 +5,9 @@ */ import { workpad } from './workpad'; -import { socketApi } from './socket'; -import { translate } from './translate'; import { esFields } from './es_fields'; -import { plugins } from './plugins'; export function routes(server) { workpad(server); - socketApi(server); - translate(server); esFields(server); - plugins(server); } diff --git a/x-pack/plugins/canvas/server/routes/plugins.js b/x-pack/plugins/canvas/server/routes/plugins.js deleted file mode 100644 index be94ef52ac9e4..0000000000000 --- a/x-pack/plugins/canvas/server/routes/plugins.js +++ /dev/null @@ -1,25 +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. - */ - -import { getPluginStream } from '../lib/get_plugin_stream'; -import { pluginPaths } from '../lib/plugin_paths'; - -export function plugins(server) { - server.route({ - method: 'GET', - path: '/api/canvas/plugins', - handler: function(request, h) { - const { type } = request.query; - - if (!pluginPaths[type]) return h.response({ error: 'Invalid type' }).code(400); - - return getPluginStream(type); - }, - config: { - auth: false, - }, - }); -} diff --git a/x-pack/plugins/canvas/server/routes/translate.js b/x-pack/plugins/canvas/server/routes/translate.js deleted file mode 100644 index 6125898a7dab9..0000000000000 --- a/x-pack/plugins/canvas/server/routes/translate.js +++ /dev/null @@ -1,34 +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. - */ - -import { fromExpression, toExpression } from '../../common/lib/ast'; - -export function translate(server) { - /* - Get AST from expression - */ - server.route({ - method: 'GET', - path: '/api/canvas/ast', - handler: function(request, h) { - if (!request.query.expression) - return h.response({ error: '"expression" query is required' }).code(400); - return fromExpression(request.query.expression); - }, - }); - - server.route({ - method: 'POST', - path: '/api/canvas/expression', - handler: function(request, h) { - try { - return toExpression(request.payload); - } catch (e) { - return h.response({ error: e.message }).code(400); - } - }, - }); -} diff --git a/x-pack/plugins/canvas/server/usage/collector.js b/x-pack/plugins/canvas/server/usage/collector.js index a4e73ffe85071..d76d023f7c7e4 100644 --- a/x-pack/plugins/canvas/server/usage/collector.js +++ b/x-pack/plugins/canvas/server/usage/collector.js @@ -5,8 +5,8 @@ */ import { sum as arraySum, min as arrayMin, max as arrayMax, get } from 'lodash'; +import { fromExpression } from '@kbn/interpreter/common/lib/ast'; import { CANVAS_USAGE_TYPE, CANVAS_TYPE } from '../../common/lib/constants'; -import { fromExpression } from '../../common/lib/ast'; /* * @param ast: an ast that includes functions to track diff --git a/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js b/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js index c53eccd87bd97..8b8f3601d86e9 100644 --- a/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js +++ b/x-pack/plugins/canvas/tasks/helpers/webpack.plugins.js @@ -21,7 +21,6 @@ module.exports = { 'uis/arguments/all': path.join(sourceDir, 'uis/arguments/register.js'), 'functions/browser/all': path.join(sourceDir, 'functions/browser/register.js'), 'functions/common/all': path.join(sourceDir, 'functions/common/register.js'), - 'types/all': path.join(sourceDir, 'types/register.js'), }, // there were problems with the node and web targets since this code is actually