diff --git a/docs/development/core-development.asciidoc b/docs/development/core-development.asciidoc index 45f52c16ee332c..ed04a6f12eae9b 100644 --- a/docs/development/core-development.asciidoc +++ b/docs/development/core-development.asciidoc @@ -15,4 +15,6 @@ include::core/development-modules.asciidoc[] include::core/development-elasticsearch.asciidoc[] +include::core/development-unit-tests.asciidoc[] + include::core/development-functional-tests.asciidoc[] diff --git a/docs/development/core/development-unit-tests.asciidoc b/docs/development/core/development-unit-tests.asciidoc new file mode 100644 index 00000000000000..852d1fef6b32a2 --- /dev/null +++ b/docs/development/core/development-unit-tests.asciidoc @@ -0,0 +1,80 @@ +[[development-unit-tests]] +=== Unit Testing + +We use unit tests to make sure that individual software units of Kibana perform as they were designed to. + +[float] +==== Current Frameworks + +Kibana is migrating unit testing from `Mocha` to `Jest`. Legacy unit tests still exist in `Mocha` but all new unit tests should be written in `Jest`. + +[float] +==== Mocha (legacy) + +Mocha tests are contained in `__tests__` directories. + +===== Running Mocha Unit Tests + +["source","shell"] +----------- +yarn test:mocha +----------- + +==== Jest +Jest tests are stored in the same directory as source code files with the `.test.{js,ts,tsx}` suffix. + +===== Running Jest Unit Tests + +["source","shell"] +----------- +yarn test:jest +----------- + +===== Writing Jest Unit Tests + +In order to write those tests there are two main things you need to be aware of. +The first one is the different between `jest.mock` and `jest.doMock` +and the second one our `jest mocks file pattern`. As we are running `js` and `ts` +test files with `babel-jest` both techniques are needed +specially for the tests implemented on Typescript in order to benefit from the +auto-inference types feature. + + +====== Jest.mock vs Jest.doMock + +Both methods are essentially the same on their roots however the `jest.mock` +calls will get hoisted to the top of the file and can only reference variables +prefixed with `mock`. On the other hand, `jest.doMock` won't be hoisted and can +reference pretty much any variable we want, however we have to assure those referenced +variables are instantiated at the time we need them which lead us to the next +section where we'll talk about our jest mock files pattern. + +====== Jest Mock Files Pattern + +Specially on typescript it is pretty common to have in unit tests +`jest.doMock` calls which reference for example imported types. Any error +will thrown from doing that however the test will fail. The reason behind that +is because despite the `jest.doMock` isn't being hoisted by `babel-jest` the +import with the types we are referencing will be hoisted to the top and at the +time we'll call the function that variable would not be defined. + +In order to prevent that we develop a protocol that should be followed: + +- Each module could provide a standard mock in `mymodule.mock.ts` in case +there are other tests that could benefit from using definitions here. +This file would not have any `jest.mock` calls, just dummy objects. + +- Each test defines its mocks in `mymodule.test.mocks.ts`. This file +could import relevant mocks from the generalised module's mocks +file `(*.mock.ts)` and call `jest.mock` for each of them. If there is +any relevant dummy mock objects to generalise (and to be used by +other tests), the dummy objects could be defined directly on this file. + +- Each test would import its mocks from the test mocks +file mymodule.test.mocks.ts. `mymodule.test.ts` has an import +like: `import * as Mocks from './mymodule.test.mocks'`, +`import { mockX } from './mymodule.test.mocks'` +or just `import './mymodule.test.mocks'` if there isn't anything +exported to be used. + + diff --git a/package.json b/package.json index 30bd3f9d52897b..3d3a64a56e671a 100644 --- a/package.json +++ b/package.json @@ -90,11 +90,13 @@ "**/@types/*/**", "**/grunt-*", "**/grunt-*/**", - "x-pack/typescript", - "kbn_tp_*/**" + "x-pack/typescript" ] }, "dependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", + "@babel/register": "^7.0.0", "@elastic/datemath": "5.0.2", "@elastic/eui": "9.5.0", "@elastic/filesaver": "1.1.2", @@ -124,10 +126,7 @@ "angular-sanitize": "1.6.5", "angular-sortable-view": "0.0.15", "autoprefixer": "^9.1.0", - "babel-core": "6.26.3", - "babel-loader": "7.1.5", - "babel-polyfill": "6.26.0", - "babel-register": "6.26.0", + "babel-loader": "8.0.5", "bluebird": "3.5.3", "boom": "^7.2.0", "brace": "0.11.1", @@ -264,7 +263,7 @@ "@octokit/rest": "^15.10.0", "@types/angular": "1.6.50", "@types/angular-mocks": "^1.7.0", - "@types/babel-core": "^6.25.5", + "@types/babel__core": "^7.1.0", "@types/bluebird": "^3.1.1", "@types/boom": "^7.2.0", "@types/chance": "^1.0.0", @@ -276,7 +275,7 @@ "@types/delete-empty": "^2.0.0", "@types/elasticsearch": "^5.0.30", "@types/enzyme": "^3.1.12", - "@types/eslint": "^4.16.2", + "@types/eslint": "^4.16.6", "@types/execa": "^0.9.0", "@types/fetch-mock": "7.2.1", "@types/getopts": "^2.0.0", @@ -321,8 +320,8 @@ "@types/zen-observable": "^0.8.0", "angular-mocks": "1.4.7", "archiver": "^3.0.0", - "babel-eslint": "^9.0.0", - "babel-jest": "^23.6.0", + "babel-eslint": "^10.0.1", + "babel-jest": "^24.1.0", "backport": "4.4.1", "chai": "3.5.0", "chance": "1.0.10", @@ -336,17 +335,17 @@ "enzyme-adapter-react-16": "^1.9.0", "enzyme-adapter-utils": "^1.10.0", "enzyme-to-json": "^3.3.4", - "eslint": "^5.6.0", - "eslint-config-prettier": "^3.1.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.26.2", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-mocha": "^5.2.0", + "eslint": "^5.15.1", + "eslint-config-prettier": "^4.1.0", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-prettier": "^2.6.2", - "eslint-plugin-react": "^7.11.1", + "eslint-plugin-prettier": "^3.0.1", + "eslint-plugin-react": "^7.12.4", "faker": "1.1.0", "fetch-mock": "7.3.0", "geckodriver": "1.12.2", @@ -357,7 +356,7 @@ "grunt-karma": "2.0.0", "grunt-peg": "^2.0.1", "grunt-run": "0.7.0", - "gulp-babel": "^7.0.1", + "gulp-babel": "^8.0.0", "gulp-sourcemaps": "2.6.4", "has-ansi": "^3.0.0", "image-diff": "1.6.0", @@ -403,9 +402,6 @@ "supertest": "^3.1.0", "supertest-as-promised": "^4.0.2", "tree-kill": "^1.1.0", - "ts-jest": "^23.1.4", - "ts-loader": "^5.2.2", - "ts-node": "^7.0.1", "tslint": "^5.11.0", "tslint-config-prettier": "^1.15.0", "tslint-microsoft-contrib": "^6.0.0", diff --git a/packages/elastic-datemath/.babelrc b/packages/elastic-datemath/.babelrc index e39c0afafdd9b3..26138d48b71b78 100644 --- a/packages/elastic-datemath/.babelrc +++ b/packages/elastic-datemath/.babelrc @@ -1,13 +1,16 @@ { - "presets": [["env", { - "targets": { - "node": "current", - "browsers": [ - "last 2 versions", - "> 5%", - "Safari 7", - ] + "presets": [ + ["@babel/preset-env", { + "targets": { + "node": "current", + "browsers": [ + "last 2 versions", + "> 5%", + "Safari 7" + ] + } } - }]], + ] + ], "plugins": ["add-module-exports"] -} \ No newline at end of file +} diff --git a/packages/elastic-datemath/package.json b/packages/elastic-datemath/package.json index 3b626077f5eafd..77c545709a3cf5 100644 --- a/packages/elastic-datemath/package.json +++ b/packages/elastic-datemath/package.json @@ -11,9 +11,9 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-plugin-add-module-exports": "^0.2.1", - "babel-preset-env": "^1.7.0", + "@babel/cli": "^7.2.3", + "@babel/preset-env": "^7.3.4", + "babel-plugin-add-module-exports": "^1.0.0", "moment": "^2.13.0" }, "dependencies": { diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index d2e639eebbbe33..c4a5a99e4c976d 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -15,15 +15,15 @@ }, "homepage": "https://github.com/elastic/eslint-config-kibana#readme", "peerDependencies": { - "babel-eslint": "^9.0.0", - "eslint": "^5.6.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.22.1", - "eslint-plugin-mocha": "^5.2.0", + "babel-eslint": "^10.0.1", + "eslint": "^5.14.1", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.11.1" + "eslint-plugin-react": "^7.12.4" } } diff --git a/packages/kbn-babel-code-parser/package.json b/packages/kbn-babel-code-parser/package.json index 23e7c29f22dfd4..addc5302856592 100755 --- a/packages/kbn-babel-code-parser/package.json +++ b/packages/kbn-babel-code-parser/package.json @@ -15,7 +15,7 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "babel-cli": "^6.26.0" + "@babel/cli": "^7.2.3" }, "dependencies": { "@kbn/babel-preset": "1.0.0", diff --git a/packages/kbn-babel-preset/common_preset.js b/packages/kbn-babel-preset/common_preset.js index a2d4495adc54b8..e67a2db5a38009 100644 --- a/packages/kbn-babel-preset/common_preset.js +++ b/packages/kbn-babel-preset/common_preset.js @@ -19,20 +19,33 @@ module.exports = { presets: [ - require.resolve('babel-preset-react'), + require.resolve('@babel/preset-typescript'), + require.resolve('@babel/preset-react') ], plugins: [ require.resolve('babel-plugin-add-module-exports'), - // stage 3 - require.resolve('babel-plugin-transform-async-generator-functions'), - require.resolve('babel-plugin-transform-object-rest-spread'), - // the class properties proposal was merged with the private fields proposal + // The class properties proposal was merged with the private fields proposal // into the "class fields" proposal. Babel doesn't support this combined // proposal yet, which includes private field, so this transform is // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 // // See https://github.com/babel/proposals/issues/12 for progress - require.resolve('babel-plugin-transform-class-properties'), + require.resolve('@babel/plugin-proposal-class-properties'), ], + overrides: [ + { + // Babel 7 don't support the namespace feature on typescript code. + // With namespaces only used for type declarations, we can securely + // strip them off for babel on x-pack infra plugin + // + // See https://github.com/babel/babel/issues/8244#issuecomment-466548733 + test: /x-pack[\/\\]plugins[\/\\]infra[\/\\].*[\/\\]graphql/, + plugins: [ + [ + require.resolve('babel-plugin-typescript-strip-namespaces'), + ], + ] + } + ] }; diff --git a/packages/kbn-babel-preset/common_preset_7.js b/packages/kbn-babel-preset/common_preset_7.js deleted file mode 100644 index df72f382e2b0a3..00000000000000 --- a/packages/kbn-babel-preset/common_preset_7.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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. - */ - -module.exports = { - presets: [ - require.resolve('@babel/preset-react'), - require.resolve('@babel/preset-typescript'), - ], - plugins: [ - require.resolve('babel7-plugin-add-module-exports'), - // stage 3 - require.resolve('@babel/plugin-proposal-async-generator-functions'), - require.resolve('@babel/plugin-proposal-object-rest-spread'), - - // the class properties proposal was merged with the private fields proposal - // into the "class fields" proposal. Babel doesn't support this combined - // proposal yet, which includes private field, so this transform is - // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 - // - // See https://github.com/babel/proposals/issues/12 for progress - require.resolve('@babel/plugin-proposal-class-properties'), - ], -}; diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index 04d6dd3609e8ad..ac4dc17e63803d 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -17,34 +17,37 @@ * under the License. */ -module.exports = { - presets: [ - [ - require.resolve('babel-preset-env'), - { - targets: { - // only applies the necessary transformations based on the - // current node.js processes version. For example: running - // `nvm install 8 && node ./src/cli` will run kibana in node - // version 8 and babel will stop transpiling async/await - // because they are supported in the "current" version of node - node: 'current', - }, +module.exports = () => { + return { + presets: [ + [ + require.resolve('@babel/preset-env'), + { + targets: { + // only applies the necessary transformations based on the + // current node.js processes version. For example: running + // `nvm install 8 && node ./src/cli` will run kibana in node + // version 8 and babel will stop transpiling async/await + // because they are supported in the "current" version of node + node: 'current', + }, - // replaces `import "babel-polyfill"` with a list of require statements - // for just the polyfills that the target versions don't already supply - // on their own - useBuiltIns: true, - }, + // replaces `import "@babel/polyfill"` with a list of require statements + // for just the polyfills that the target versions don't already supply + // on their own + useBuiltIns: 'entry', + modules: 'cjs' + }, + ], + require('./common_preset'), ], - require('./common_preset'), - ], - plugins: [ - [ - require.resolve('babel-plugin-transform-define'), - { - 'global.__BUILT_WITH_BABEL__': 'true' - } + plugins: [ + [ + require.resolve('babel-plugin-transform-define'), + { + 'global.__BUILT_WITH_BABEL__': 'true' + } + ] ] - ] + }; }; diff --git a/packages/kbn-babel-preset/node_preset_7.js b/packages/kbn-babel-preset/node_preset_7.js deleted file mode 100644 index b57dd58dd9f154..00000000000000 --- a/packages/kbn-babel-preset/node_preset_7.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -module.exports = () => ({ - presets: [ - [ - require.resolve('@babel/preset-env'), - { - targets: { - // only applies the necessary transformations based on the - // current node.js processes version. For example: running - // `nvm install 8 && node ./src/cli` will run kibana in node - // version 8 and babel will stop transpiling async/await - // because they are supported in the "current" version of node - node: 'current', - }, - - // replaces `import "babel-polyfill"` with a list of require statements - // for just the polyfills that the target versions don't already supply - // on their own - useBuiltIns: 'entry', - }, - ], - require('./common_preset_7'), - ], - plugins: [ - [ - require.resolve('babel-plugin-transform-define'), - { - 'global.__BUILT_WITH_BABEL__': 'true' - } - ] - ] -}); diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 41c03c05426757..79ee6bbe39c0ce 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -4,20 +4,12 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.3.4", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", "@babel/plugin-proposal-class-properties": "^7.3.4", - "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/preset-react":"^7.0.0", "@babel/preset-env": "^7.3.4", - "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.3.3", - "babel-plugin-add-module-exports": "^0.2.1", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-add-module-exports": "^1.0.0", "babel-plugin-transform-define": "^1.3.1", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-preset-env": "^1.7.0", - "babel-preset-react": "^6.24.1", - "babel7-plugin-add-module-exports": "npm:babel-plugin-add-module-exports@^1.0.0" + "babel-plugin-typescript-strip-namespaces": "^1.1.1" } } diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 97bfa44a049d93..df5745bc33f895 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -17,21 +17,24 @@ * under the License. */ -module.exports = { - presets: [ - [ - require.resolve('babel-preset-env'), - { - targets: { - browsers: [ - 'last 2 versions', - '> 5%', - 'Safari 7', // for PhantomJS support: https://github.com/elastic/kibana/issues/27136 - ], +module.exports = () => { + return { + presets: [ + [ + require.resolve('@babel/preset-env'), + { + targets: { + browsers: [ + 'last 2 versions', + '> 5%', + 'Safari 7', // for PhantomJS support: https://github.com/elastic/kibana/issues/27136 + ], + }, + useBuiltIns: 'entry', + modules: 'cjs' }, - useBuiltIns: true, - }, - ], - require('./common_preset'), - ] + ], + require('./common_preset'), + ] + }; }; diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index af39ffecf6690c..4fbc80d6e679a6 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -19,9 +19,9 @@ "tslib": "^1.9.3" }, "devDependencies": { + "@babel/cli": "^7.2.3", "@kbn/babel-preset": "1.0.0", "@kbn/expect": "1.0.0", - "babel-cli": "^6.26.0", "chance": "1.0.6" } } diff --git a/packages/kbn-eslint-plugin-eslint/package.json b/packages/kbn-eslint-plugin-eslint/package.json index b35387384071ed..e2024b54a620c2 100644 --- a/packages/kbn-eslint-plugin-eslint/package.json +++ b/packages/kbn-eslint-plugin-eslint/package.json @@ -4,8 +4,8 @@ "private": true, "license": "Apache-2.0", "peerDependencies": { - "eslint": "^5.6.0", - "babel-eslint": "^9.0.0" + "eslint": "^5.14.1", + "babel-eslint": "^10.0.1" }, "dependencies": { "dedent": "^0.7.0" diff --git a/packages/kbn-i18n/tsconfig.json b/packages/kbn-i18n/tsconfig.json index 3b757d1240bdc6..d3dae3078c1d7d 100644 --- a/packages/kbn-i18n/tsconfig.json +++ b/packages/kbn-i18n/tsconfig.json @@ -1,20 +1,20 @@ -{ - "extends": "../../tsconfig.json", - "include": [ - "src/**/*.ts", - "src/**/*.tsx", - "types/intl_format_cache.d.ts", - "types/intl_relativeformat.d.ts" - ], - "exclude": [ - "target" - ], - "compilerOptions": { - "declaration": true, - "declarationDir": "./target/types", - "types": [ - "jest", - "node" - ] - } -} +{ + "extends": "../../tsconfig.json", + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "types/intl_format_cache.d.ts", + "types/intl_relativeformat.d.ts" + ], + "exclude": [ + "target" + ], + "compilerOptions": { + "declaration": true, + "declarationDir": "./target/types", + "types": [ + "jest", + "node" + ] + } +} diff --git a/packages/kbn-interpreter/.babelrc b/packages/kbn-interpreter/.babelrc index 57a5cc3669eb4d..875cbcde9d0e1d 100644 --- a/packages/kbn-interpreter/.babelrc +++ b/packages/kbn-interpreter/.babelrc @@ -1,8 +1,7 @@ { "presets": ["@kbn/babel-preset/webpack_preset"], "plugins": [ - ["babel-plugin-transform-runtime", { - "polyfill": false, + ["@babel/plugin-transform-runtime", { "regenerator": true }] ] diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index 290e02cb2b2e7f..ded8f38bff492e 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -9,19 +9,20 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { + "@babel/runtime": "^7.3.4", "@kbn/i18n": "1.0.0", "lodash": "npm:@elastic/lodash@3.10.1-kibana1", "lodash.clone": "^4.5.0", "uuid": "3.0.1" }, "devDependencies": { + "@babel/cli": "^7.2.3", + "@babel/core": "7.3.4", + "@babel/plugin-transform-runtime": "^7.3.4", + "@babel/polyfill": "7.2.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", - "babel-cli": "^6.26.0", - "babel-core": "6.26.3", - "babel-loader": "7.1.5", - "babel-plugin-transform-runtime": "^6.23.0", - "babel-polyfill": "6.20.0", + "babel-loader": "8.0.5", "copy-webpack-plugin": "^4.6.0", "css-loader": "1.0.0", "del": "^3.0.0", diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.js index 5db4dc13640cb1..b1185f47521965 100644 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.js +++ b/packages/kbn-interpreter/tasks/build/server_code_transformer.js @@ -19,7 +19,7 @@ const { extname } = require('path'); -const { transform } = require('babel-core'); +const { transform } = require('@babel/core'); exports.createServerCodeTransformer = (sourceMaps) => { return (content, path) => { diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js index 01dc9323352ae4..519e529c20bf5e 100644 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js +++ b/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js @@ -28,15 +28,14 @@ describe('js support', () => { it('transpiles js file', () => { const transformer = createServerCodeTransformer(); expect(transformer(JS_FIXTURE, JS_FIXTURE_PATH)).toMatchInlineSnapshot(` -"'use strict'; +"\\"use strict\\"; -var _util = require('util'); - -var _util2 = _interopRequireDefault(_util); +var _util = _interopRequireDefault(require(\\"util\\")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -console.log(_util2.default.format('hello world')); /* eslint-disable */" +/* eslint-disable */ +console.log(_util.default.format('hello world'));" `); }); diff --git a/packages/kbn-plugin-generator/sao_template/template/package_template.json b/packages/kbn-plugin-generator/sao_template/template/package_template.json index 80e6ae8642e15f..7a6d0842a1649e 100644 --- a/packages/kbn-plugin-generator/sao_template/template/package_template.json +++ b/packages/kbn-plugin-generator/sao_template/template/package_template.json @@ -27,15 +27,15 @@ "@elastic/eslint-import-resolver-kibana": "link:../../kibana/packages/kbn-eslint-import-resolver-kibana", "@kbn/expect": "1.0.0", "@kbn/plugin-helpers": "link:../../kibana/packages/kbn-plugin-helpers", - "babel-eslint": "^9.0.0", - "eslint": "^5.6.0", - "eslint-plugin-babel": "^5.2.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jest": "^21.26.2", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-mocha": "^5.2.0", + "babel-eslint": "^10.0.1", + "eslint": "^5.14.1", + "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "^22.3.0", + "eslint-plugin-jsx-a11y": "^6.2.1", + "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-react": "^7.11.1" + "eslint-plugin-react": "^7.12.4" } } diff --git a/packages/kbn-plugin-helpers/lib/utils.js b/packages/kbn-plugin-helpers/lib/utils.js index ee82b9a8fd57d7..d9a5b9148208f1 100644 --- a/packages/kbn-plugin-helpers/lib/utils.js +++ b/packages/kbn-plugin-helpers/lib/utils.js @@ -25,7 +25,7 @@ function babelRegister() { const plugin = pluginConfig(); try { - // add support for moved babel-register source: https://github.com/elastic/kibana/pull/13973 + // add support for moved @babel/register source: https://github.com/elastic/kibana/pull/13973 require(resolve(plugin.kibanaRoot, 'src/setup_node_env/babel_register')); // eslint-disable-line import/no-dynamic-require } catch (error) { if (error.code === 'MODULE_NOT_FOUND') { diff --git a/packages/kbn-pm/.babelrc b/packages/kbn-pm/.babelrc index f34e55f9b7ba65..1ca768097a7ee8 100644 --- a/packages/kbn-pm/.babelrc +++ b/packages/kbn-pm/.babelrc @@ -1,10 +1,14 @@ { "presets": [ - "stage-3", - ["env", { + "@babel/typescript", + ["@babel/preset-env", { "targets": { "node": "current" } }] + ], + "plugins": [ + "@babel/proposal-class-properties", + "@babel/proposal-object-rest-spread" ] -} \ No newline at end of file +} diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 5910f00408b179..808f72116f8151 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -87,146 +87,90 @@ module.exports = /************************************************************************/ /******/ ([ /* 0 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(367); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); -Object.defineProperty(exports, "__esModule", { - value: true -}); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -var _cli = __webpack_require__(1); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(131); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_2__["copyWorkspacePackages"]; }); -Object.defineProperty(exports, 'run', { - enumerable: true, - get: function () { - return _cli.run; - } -}); - -var _production = __webpack_require__(367); +/* + * 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. + */ -Object.defineProperty(exports, 'buildProductionProjects', { - enumerable: true, - get: function () { - return _production.buildProductionProjects; - } -}); -Object.defineProperty(exports, 'prepareExternalProjectDependencies', { - enumerable: true, - get: function () { - return _production.prepareExternalProjectDependencies; - } -}); -var _workspaces = __webpack_require__(131); -Object.defineProperty(exports, 'copyWorkspacePackages', { - enumerable: true, - get: function () { - return _workspaces.copyWorkspacePackages; - } -}); /***/ }), /* 1 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "run", function() { return run; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var getopts__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); +/* harmony import */ var getopts__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(getopts__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(357); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.run = undefined; - -let run = exports.run = (() => { - var _ref = _asyncToGenerator(function* (argv) { - // We can simplify this setup (and remove this extra handling) once Yarn - // starts forwarding the `--` directly to this script, see - // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 - if (argv.includes('--')) { - _log.log.write(_chalk2.default.red(`Using "--" is not allowed, as it doesn't work with 'yarn kbn'.`)); - process.exit(1); - } - const options = (0, _getopts2.default)(argv, { - alias: { - e: 'exclude', - h: 'help', - i: 'include' - }, - boolean: ['prefer-offline', 'frozen-lockfile'] - }); - const args = options._; - if (options.help || args.length === 0) { - help(); - return; - } - // This `rootPath` is relative to `./dist/` as that's the location of the - // built version of this tool. - const rootPath = (0, _path.resolve)(__dirname, '../../../'); - const commandName = args[0]; - const extraArgs = args.slice(1); - const commandOptions = { options, extraArgs, rootPath }; - const command = _commands.commands[commandName]; - if (command === undefined) { - _log.log.write(_chalk2.default.red(`[${commandName}] is not a valid command, see 'kbn --help'`)); - process.exit(1); - } - yield (0, _run.runCommand)(command, commandOptions); - }); - - return function run(_x) { - return _ref.apply(this, arguments); - }; -})(); - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _dedent = __webpack_require__(14); - -var _dedent2 = _interopRequireDefault(_dedent); - -var _getopts = __webpack_require__(15); - -var _getopts2 = _interopRequireDefault(_getopts); - -var _path = __webpack_require__(16); - -var _commands = __webpack_require__(17); -var _run = __webpack_require__(357); -var _log = __webpack_require__(33); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ function help() { - const availableCommands = Object.keys(_commands.commands).map(commandName => _commands.commands[commandName]).map(command => `${command.name} - ${command.description}`); - _log.log.write(_dedent2.default` + const availableCommands = Object.keys(_commands__WEBPACK_IMPORTED_MODULE_4__["commands"]).map(commandName => _commands__WEBPACK_IMPORTED_MODULE_4__["commands"][commandName]).map(command => `${command.name} - ${command.description}`); + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(dedent__WEBPACK_IMPORTED_MODULE_1___default.a` usage: kbn [] By default commands are run for Kibana itself, all packages in the 'packages/' @@ -245,6 +189,50 @@ function help() { `); } +async function run(argv) { + // We can simplify this setup (and remove this extra handling) once Yarn + // starts forwarding the `--` directly to this script, see + // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 + if (argv.includes('--')) { + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`Using "--" is not allowed, as it doesn't work with 'yarn kbn'.`)); + process.exit(1); + } + + const options = getopts__WEBPACK_IMPORTED_MODULE_2___default()(argv, { + alias: { + e: 'exclude', + h: 'help', + i: 'include' + }, + boolean: ['prefer-offline', 'frozen-lockfile'] + }); + const args = options._; + + if (options.help || args.length === 0) { + help(); + return; + } // This `rootPath` is relative to `./dist/` as that's the location of the + // built version of this tool. + + + const rootPath = Object(path__WEBPACK_IMPORTED_MODULE_3__["resolve"])(__dirname, '../../../'); + const commandName = args[0]; + const extraArgs = args.slice(1); + const commandOptions = { + options, + extraArgs, + rootPath + }; + const command = _commands__WEBPACK_IMPORTED_MODULE_4__["commands"][commandName]; + + if (command === undefined) { + _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`[${commandName}] is not a valid command, see 'kbn --help'`)); + process.exit(1); + } + + await Object(_run__WEBPACK_IMPORTED_MODULE_5__["runCommand"])(command, commandOptions); +} + /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { @@ -2452,24 +2440,15 @@ module.exports = require("path"); /***/ }), /* 17 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.commands = undefined; - -var _bootstrap = __webpack_require__(18); - -var _clean = __webpack_require__(133); - -var _run = __webpack_require__(155); - -var _watch = __webpack_require__(156); - +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); +/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(133); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(155); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(156); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2488,117 +2467,137 @@ var _watch = __webpack_require__(156); * specific language governing permissions and limitations * under the License. */ -const commands = exports.commands = { - bootstrap: _bootstrap.BootstrapCommand, - clean: _clean.CleanCommand, - run: _run.RunCommand, - watch: _watch.WatchCommand + + + + +const commands = { + bootstrap: _bootstrap__WEBPACK_IMPORTED_MODULE_0__["BootstrapCommand"], + clean: _clean__WEBPACK_IMPORTED_MODULE_1__["CleanCommand"], + run: _run__WEBPACK_IMPORTED_MODULE_2__["RunCommand"], + watch: _watch__WEBPACK_IMPORTED_MODULE_3__["WatchCommand"] }; /***/ }), /* 18 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCommand", function() { return BootstrapCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.BootstrapCommand = undefined; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _link_project_executables = __webpack_require__(19); -var _log = __webpack_require__(33); -var _parallelize = __webpack_require__(34); -var _projects = __webpack_require__(35); +const BootstrapCommand = { + description: 'Install dependencies and crosslink projects', + name: 'bootstrap', -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + async run(projects, projectGraph, { + options + }) { + const batchedProjectsByWorkspace = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph, { + batchByWorkspace: true + }); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_4__["topologicallyBatchProjects"])(projects, projectGraph); + const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nRunning installs in topological order:')); + + for (const batch of batchedProjectsByWorkspace) { + for (const project of batch) { + if (project.isWorkspaceProject) { + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(`Skipping workspace project: ${project.name}`); + continue; + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (project.hasDependencies()) { + await project.installDependencies({ + extraArgs + }); + } + } + } + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nInstalls completed, linking package executables:\n')); + await Object(_utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__["linkProjectExecutables"])(projects, projectGraph); + /** + * At the end of the bootstrapping process we call all `kbn:bootstrap` scripts + * in the list of projects. We do this because some projects need to be + * transpiled before they can be used. Ideally we shouldn't do this unless we + * have to, as it will slow down the bootstrapping process. + */ -const BootstrapCommand = exports.BootstrapCommand = { - description: 'Install dependencies and crosslink projects', - name: 'bootstrap', - run(projects, projectGraph, { options }) { - return _asyncToGenerator(function* () { - const batchedProjectsByWorkspace = (0, _projects.topologicallyBatchProjects)(projects, projectGraph, { - batchByWorkspace: true - }); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - const extraArgs = [...(options['frozen-lockfile'] === true ? ['--frozen-lockfile'] : []), ...(options['prefer-offline'] === true ? ['--prefer-offline'] : [])]; - _log.log.write(_chalk2.default.bold('\nRunning installs in topological order:')); - for (const batch of batchedProjectsByWorkspace) { - for (const project of batch) { - if (project.isWorkspaceProject) { - _log.log.write(`Skipping workspace project: ${project.name}`); - continue; - } - if (project.hasDependencies()) { - yield project.installDependencies({ extraArgs }); - } - } - } - _log.log.write(_chalk2.default.bold('\nInstalls completed, linking package executables:\n')); - yield (0, _link_project_executables.linkProjectExecutables)(projects, projectGraph); - /** - * At the end of the bootstrapping process we call all `kbn:bootstrap` scripts - * in the list of projects. We do this because some projects need to be - * transpiled before they can be used. Ideally we shouldn't do this unless we - * have to, as it will slow down the bootstrapping process. - */ - _log.log.write(_chalk2.default.bold('\nLinking executables completed, running `kbn:bootstrap` scripts\n')); - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - if (pkg.hasScript('kbn:bootstrap')) { - yield pkg.runScriptStreaming('kbn:bootstrap'); - } - }); + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold('\nLinking executables completed, running `kbn:bootstrap` scripts\n')); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_3__["parallelizeBatches"])(batchedProjects, async pkg => { + if (pkg.hasScript('kbn:bootstrap')) { + await pkg.runScriptStreaming('kbn:bootstrap'); + } + }); + _utils_log__WEBPACK_IMPORTED_MODULE_2__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green.bold('\nBootstrapping completed!\n')); + } - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - _log.log.write(_chalk2.default.green.bold('\nBootstrapping completed!\n')); - })(); - } }; /***/ }), /* 19 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "linkProjectExecutables", function() { return linkProjectExecutables; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(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. + */ + + -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.linkProjectExecutables = undefined; /** * Yarn does not link the executables from dependencies that are installed @@ -2608,130 +2607,122 @@ exports.linkProjectExecutables = undefined; * dependencies, and manually linking their executables if defined. The logic * for linking was mostly adapted from lerna: https://github.com/lerna/lerna/blob/1d7eb9eeff65d5a7de64dea73613b1bf6bfa8d57/src/PackageUtilities.js#L348 */ -let linkProjectExecutables = exports.linkProjectExecutables = (() => { - var _ref = _asyncToGenerator(function* (projectsByName, projectGraph) { - for (const [projectName, projectDeps] of projectGraph) { - const project = projectsByName.get(projectName); - const binsDir = (0, _path.resolve)(project.nodeModulesLocation, '.bin'); - for (const projectDep of projectDeps) { - const executables = projectDep.getExecutables(); - for (const name of Object.keys(executables)) { - const srcPath = executables[name]; - // existing logic from lerna -- ensure that the bin we are going to - // point to exists or ignore it - if (!(yield (0, _fs.isFile)(srcPath))) { - continue; - } - const dest = (0, _path.resolve)(binsDir, name); - // Get relative project path with normalized path separators. - const projectRelativePath = (0, _path.relative)(project.path, srcPath).split(_path.sep).join('/'); - _log.log.write(_chalk2.default`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`); - yield (0, _fs.mkdirp)((0, _path.dirname)(dest)); - yield (0, _fs.createSymlink)(srcPath, dest, 'exec'); - yield (0, _fs.chmod)(dest, '755'); - } - } - } - }); - - return function linkProjectExecutables(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); +async function linkProjectExecutables(projectsByName, projectGraph) { + for (const [projectName, projectDeps] of projectGraph) { + const project = projectsByName.get(projectName); + const binsDir = Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(project.nodeModulesLocation, '.bin'); -var _path = __webpack_require__(16); + for (const projectDep of projectDeps) { + const executables = projectDep.getExecutables(); -var _chalk = __webpack_require__(2); + for (const name of Object.keys(executables)) { + const srcPath = executables[name]; // existing logic from lerna -- ensure that the bin we are going to + // point to exists or ignore it -var _chalk2 = _interopRequireDefault(_chalk); - -var _fs = __webpack_require__(20); - -var _log = __webpack_require__(33); + if (!(await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["isFile"])(srcPath))) { + continue; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + const dest = Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(binsDir, name); // Get relative project path with normalized path separators. -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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 projectRelativePath = Object(path__WEBPACK_IMPORTED_MODULE_0__["relative"])(project.path, srcPath).split(path__WEBPACK_IMPORTED_MODULE_0__["sep"]).join('/'); + _log__WEBPACK_IMPORTED_MODULE_3__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_1___default.a`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["mkdirp"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["dirname"])(dest)); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["createSymlink"])(srcPath, dest, 'exec'); + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["chmod"])(dest, '755'); + } + } + } +} /***/ }), /* 20 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unlink", function() { return unlink; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyDirectory", function() { return copyDirectory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "chmod", function() { return chmod; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readFile", function() { return readFile; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mkdirp", function() { return mkdirp; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isDirectory", function() { return isDirectory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFile", function() { return isFile; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createSymlink", function() { return createSymlink; }); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cmd_shim__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); +/* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(mkdirp__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(32); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ncp__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_5__); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createSymlink = exports.isFile = exports.isDirectory = exports.mkdirp = exports.readFile = exports.chmod = exports.copyDirectory = exports.unlink = undefined; -let statTest = (() => { - var _ref = _asyncToGenerator(function* (path, block) { - try { - return block((yield stat(path))); - } catch (e) { - if (e.code === 'ENOENT') { - return false; - } - throw e; - } - }); - return function statTest(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + + +const stat = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.stat); +const readFile = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.readFile); +const symlink = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.symlink); +const chmod = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.chmod); +const cmdShim = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(cmd_shim__WEBPACK_IMPORTED_MODULE_0___default.a); +const mkdirp = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(mkdirp__WEBPACK_IMPORTED_MODULE_2___default.a); +const unlink = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.unlink); +const copyDirectory = Object(util__WEBPACK_IMPORTED_MODULE_5__["promisify"])(ncp__WEBPACK_IMPORTED_MODULE_3__["ncp"]); + + +async function statTest(path, block) { + try { + return block((await stat(path))); + } catch (e) { + if (e.code === 'ENOENT') { + return false; + } + + throw e; + } +} /** * Test if a path points to a directory. * @param path */ -let isDirectory = exports.isDirectory = (() => { - var _ref2 = _asyncToGenerator(function* (path) { - return yield statTest(path, function (stats) { - return stats.isDirectory(); - }); - }); - - return function isDirectory(_x3) { - return _ref2.apply(this, arguments); - }; -})(); +async function isDirectory(path) { + return await statTest(path, stats => stats.isDirectory()); +} /** * Test if a path points to a regular file. * @param path */ - -let isFile = exports.isFile = (() => { - var _ref3 = _asyncToGenerator(function* (path) { - return yield statTest(path, function (stats) { - return stats.isFile(); - }); - }); - - return function isFile(_x4) { - return _ref3.apply(this, arguments); - }; -})(); +async function isFile(path) { + return await statTest(path, stats => stats.isFile()); +} /** * Create a symlink at dest that points to src. Adapted from * https://github.com/lerna/lerna/blob/2f1b87d9e2295f587e4ac74269f714271d8ed428/src/FileSystemUtilities.js#L103. @@ -2743,96 +2734,32 @@ let isFile = exports.isFile = (() => { * for executable files on windows. */ +async function createSymlink(src, dest, type) { + if (process.platform === 'win32') { + if (type === 'exec') { + await cmdShim(src, dest); + } else { + await forceCreate(src, dest, type); + } + } else { + const posixType = type === 'exec' ? 'file' : type; + const relativeSource = Object(path__WEBPACK_IMPORTED_MODULE_4__["relative"])(Object(path__WEBPACK_IMPORTED_MODULE_4__["dirname"])(dest), src); + await forceCreate(relativeSource, dest, posixType); + } +} -let createSymlink = exports.createSymlink = (() => { - var _ref4 = _asyncToGenerator(function* (src, dest, type) { - if (process.platform === 'win32') { - if (type === 'exec') { - yield cmdShim(src, dest); - } else { - yield forceCreate(src, dest, type); - } - } else { - const posixType = type === 'exec' ? 'file' : type; - const relativeSource = (0, _path.relative)((0, _path.dirname)(dest), src); - yield forceCreate(relativeSource, dest, posixType); - } - }); - - return function createSymlink(_x5, _x6, _x7) { - return _ref4.apply(this, arguments); - }; -})(); - -let forceCreate = (() => { - var _ref5 = _asyncToGenerator(function* (src, dest, type) { - try { - // If something exists at `dest` we need to remove it first. - yield unlink(dest); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } - } - yield symlink(src, dest, type); - }); - - return function forceCreate(_x8, _x9, _x10) { - return _ref5.apply(this, arguments); - }; -})(); - -var _cmdShim = __webpack_require__(21); - -var _cmdShim2 = _interopRequireDefault(_cmdShim); - -var _fs = __webpack_require__(23); - -var _fs2 = _interopRequireDefault(_fs); - -var _mkdirp = __webpack_require__(31); - -var _mkdirp2 = _interopRequireDefault(_mkdirp); - -var _ncp = __webpack_require__(32); - -var _path = __webpack_require__(16); - -var _util = __webpack_require__(29); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ - +async function forceCreate(src, dest, type) { + try { + // If something exists at `dest` we need to remove it first. + await unlink(dest); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } -const stat = (0, _util.promisify)(_fs2.default.stat); -const readFile = (0, _util.promisify)(_fs2.default.readFile); -const symlink = (0, _util.promisify)(_fs2.default.symlink); -const chmod = (0, _util.promisify)(_fs2.default.chmod); -const cmdShim = (0, _util.promisify)(_cmdShim2.default); -const mkdirp = (0, _util.promisify)(_mkdirp2.default); -const unlink = exports.unlink = (0, _util.promisify)(_fs2.default.unlink); -const copyDirectory = exports.copyDirectory = (0, _util.promisify)(_ncp.ncp); -exports.chmod = chmod; -exports.readFile = readFile; -exports.mkdirp = mkdirp; + await symlink(src, dest, type); +} /***/ }), /* 21 */ @@ -4179,14 +4106,11 @@ function ncp (source, dest, options, callback) { /***/ }), /* 33 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "log", function() { return log; }); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4205,7 +4129,7 @@ Object.defineProperty(exports, "__esModule", { * specific language governing permissions and limitations * under the License. */ -const log = exports.log = { +const log = { /** * Log something to the console. Ideally we would use a real logger in * kbn-pm, but that's a pretty big change for now. @@ -4215,19 +4139,94 @@ const log = exports.log = { // tslint:disable no-console console.log(...args); } + }; /***/ }), /* 34 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parallelizeBatches", function() { return parallelizeBatches; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parallelize", function() { return parallelize; }); +/* + * 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. + */ +async function parallelizeBatches(batches, fn) { + for (const batch of batches) { + // We need to make sure the entire batch has completed before we can move on + // to the next batch + await parallelize(batch, fn); + } +} +async function parallelize(items, fn, concurrency = 4) { + if (items.length === 0) { + return; + } + return new Promise((resolve, reject) => { + let activePromises = 0; + const values = items.slice(0); -Object.defineProperty(exports, "__esModule", { - value: true -}); + async function scheduleItem(item) { + activePromises++; + try { + await fn(item); + activePromises--; + + if (values.length > 0) { + // We have more work to do, so we schedule the next promise + scheduleItem(values.shift()); + } else if (activePromises === 0) { + // We have no more values left, and all items have completed, so we've + // completed all the work. + resolve(); + } + } catch (error) { + reject(error); + } + } + + values.splice(0, concurrency).map(scheduleItem); + }); +} + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return getProjects; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; }); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(131); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4246,252 +4245,181 @@ Object.defineProperty(exports, "__esModule", { * specific language governing permissions and limitations * under the License. */ -let parallelizeBatches = exports.parallelizeBatches = (() => { - var _ref = _asyncToGenerator(function* (batches, fn) { - for (const batch of batches) { - // We need to make sure the entire batch has completed before we can move on - // to the next batch - yield parallelize(batch, fn); - } + + + + + + +const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); +async function getProjects(rootPath, projectsPathsPatterns, { + include = [], + exclude = [] +} = {}) { + const projects = new Map(); + const workspaceProjectsPaths = await Object(_workspaces__WEBPACK_IMPORTED_MODULE_5__["workspacePackagePaths"])(rootPath); + + for (const pattern of projectsPathsPatterns) { + const pathsToProcess = await packagesFromGlobPattern({ + pattern, + rootPath }); - return function parallelizeBatches(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + for (const filePath of pathsToProcess) { + const projectConfigPath = normalize(filePath); + const projectDir = path__WEBPACK_IMPORTED_MODULE_1___default.a.dirname(projectConfigPath); + const project = await _project__WEBPACK_IMPORTED_MODULE_4__["Project"].fromPath(projectDir); -let parallelize = exports.parallelize = (() => { - var _ref2 = _asyncToGenerator(function* (items, fn, concurrency = 4) { - if (items.length === 0) { - return; - } - return new Promise(function (resolve, reject) { - let scheduleItem = (() => { - var _ref3 = _asyncToGenerator(function* (item) { - activePromises++; - try { - yield fn(item); - activePromises--; - if (values.length > 0) { - // We have more work to do, so we schedule the next promise - scheduleItem(values.shift()); - } else if (activePromises === 0) { - // We have no more values left, and all items have completed, so we've - // completed all the work. - resolve(); - } - } catch (error) { - reject(error); - } - }); + if (workspaceProjectsPaths.indexOf(filePath) >= 0) { + project.isWorkspaceProject = true; + } - return function scheduleItem(_x5) { - return _ref3.apply(this, arguments); - }; - })(); + const excludeProject = exclude.includes(project.name) || include.length > 0 && !include.includes(project.name); - let activePromises = 0; - const values = items.slice(0); + if (excludeProject) { + continue; + } - values.splice(0, concurrency).map(scheduleItem); + if (projects.has(project.name)) { + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`There are multiple projects with the same name [${project.name}]`, { + name: project.name, + paths: [project.path, projects.get(project.name).path] }); - }); + } - return function parallelize(_x3, _x4) { - return _ref2.apply(this, arguments); - }; -})(); + projects.set(project.name, project); + } + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + return projects; +} -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { +function packagesFromGlobPattern({ + pattern, + rootPath +}) { + const globOptions = { + cwd: rootPath, + // Should throw in case of unusual errors when reading the file system + strict: true, + // Always returns absolute paths for matched files + absolute: true, + // Do not match ** against multiple filenames + // (This is only specified because we currently don't have a need for it.) + noglobstar: true + }; + return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); +} // https://github.com/isaacs/node-glob/blob/master/common.js#L104 +// glob always returns "\\" as "/" in windows, so everyone +// gets normalized because we can't have nice things. -"use strict"; +function normalize(dir) { + return path__WEBPACK_IMPORTED_MODULE_1___default.a.normalize(dir); +} -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getProjects = undefined; - -let getProjects = exports.getProjects = (() => { - var _ref = _asyncToGenerator(function* (rootPath, projectsPathsPatterns, { include = [], exclude = [] } = {}) { - const projects = new Map(); - const workspaceProjectsPaths = yield (0, _workspaces.workspacePackagePaths)(rootPath); - for (const pattern of projectsPathsPatterns) { - const pathsToProcess = yield packagesFromGlobPattern({ pattern, rootPath }); - for (const filePath of pathsToProcess) { - const projectConfigPath = normalize(filePath); - const projectDir = _path2.default.dirname(projectConfigPath); - const project = yield _project.Project.fromPath(projectDir); - if (workspaceProjectsPaths.indexOf(filePath) >= 0) { - project.isWorkspaceProject = true; - } - const excludeProject = exclude.includes(project.name) || include.length > 0 && !include.includes(project.name); - if (excludeProject) { - continue; - } - if (projects.has(project.name)) { - throw new _errors.CliError(`There are multiple projects with the same name [${project.name}]`, { - name: project.name, - paths: [project.path, projects.get(project.name).path] - }); - } - projects.set(project.name, project); - } - } - return projects; - }); +function buildProjectGraph(projects) { + const projectGraph = new Map(); - return function getProjects(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + for (const project of projects.values()) { + const projectDeps = []; + const dependencies = project.allDependencies; -exports.buildProjectGraph = buildProjectGraph; -exports.topologicallyBatchProjects = topologicallyBatchProjects; -exports.includeTransitiveProjects = includeTransitiveProjects; + for (const depName of Object.keys(dependencies)) { + if (projects.has(depName)) { + const dep = projects.get(depName); + const dependentProjectIsInWorkspace = project.isWorkspaceProject || project.json.name === 'kibana'; + project.ensureValidProjectDependency(dep, dependentProjectIsInWorkspace); + projectDeps.push(dep); + } + } -var _glob = __webpack_require__(36); + projectGraph.set(project.name, projectDeps); + } -var _glob2 = _interopRequireDefault(_glob); + return projectGraph; +} +function topologicallyBatchProjects(projectsToBatch, projectGraph, { + batchByWorkspace = false +} = {}) { + // We're going to be chopping stuff out of this list, so copy it. + const projectsLeftToBatch = new Set(projectsToBatch.keys()); + const batches = []; -var _path = __webpack_require__(16); + if (batchByWorkspace) { + const workspaceRootProject = Array.from(projectsToBatch.values()).find(p => p.isWorkspaceRoot); -var _path2 = _interopRequireDefault(_path); + if (!workspaceRootProject) { + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`There was no yarn workspace root found.`); + } // Push in the workspace root first. -var _util = __webpack_require__(29); -var _errors = __webpack_require__(52); + batches.push([workspaceRootProject]); + projectsLeftToBatch.delete(workspaceRootProject.name); // In the next batch, push in all workspace projects. -var _project = __webpack_require__(53); + const workspaceBatch = []; -var _workspaces = __webpack_require__(131); + for (const projectName of projectsLeftToBatch) { + const project = projectsToBatch.get(projectName); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (project.isWorkspaceProject) { + workspaceBatch.push(project); + projectsLeftToBatch.delete(projectName); + } + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + batches.push(workspaceBatch); + } + while (projectsLeftToBatch.size > 0) { + // Get all projects that have no remaining dependencies within the repo + // that haven't yet been picked. + const batch = []; -const glob = (0, _util.promisify)(_glob2.default); + for (const projectName of projectsLeftToBatch) { + const projectDeps = projectGraph.get(projectName); + const needsDependenciesBatched = projectDeps.some(dep => projectsLeftToBatch.has(dep.name)); -function packagesFromGlobPattern({ pattern, rootPath }) { - const globOptions = { - cwd: rootPath, - // Should throw in case of unusual errors when reading the file system - strict: true, - // Always returns absolute paths for matched files - absolute: true, - // Do not match ** against multiple filenames - // (This is only specified because we currently don't have a need for it.) - noglobstar: true - }; - return glob(_path2.default.join(pattern, 'package.json'), globOptions); -} -// https://github.com/isaacs/node-glob/blob/master/common.js#L104 -// glob always returns "\\" as "/" in windows, so everyone -// gets normalized because we can't have nice things. -function normalize(dir) { - return _path2.default.normalize(dir); -} -function buildProjectGraph(projects) { - const projectGraph = new Map(); - for (const project of projects.values()) { - const projectDeps = []; - const dependencies = project.allDependencies; - for (const depName of Object.keys(dependencies)) { - if (projects.has(depName)) { - const dep = projects.get(depName); - const dependentProjectIsInWorkspace = project.isWorkspaceProject || project.json.name === 'kibana'; - project.ensureValidProjectDependency(dep, dependentProjectIsInWorkspace); - projectDeps.push(dep); - } - } - projectGraph.set(project.name, projectDeps); - } - return projectGraph; -} -function topologicallyBatchProjects(projectsToBatch, projectGraph, { batchByWorkspace = false } = {}) { - // We're going to be chopping stuff out of this list, so copy it. - const projectsLeftToBatch = new Set(projectsToBatch.keys()); - const batches = []; - if (batchByWorkspace) { - const workspaceRootProject = Array.from(projectsToBatch.values()).find(p => p.isWorkspaceRoot); - if (!workspaceRootProject) { - throw new _errors.CliError(`There was no yarn workspace root found.`); - } - // Push in the workspace root first. - batches.push([workspaceRootProject]); - projectsLeftToBatch.delete(workspaceRootProject.name); - // In the next batch, push in all workspace projects. - const workspaceBatch = []; - for (const projectName of projectsLeftToBatch) { - const project = projectsToBatch.get(projectName); - if (project.isWorkspaceProject) { - workspaceBatch.push(project); - projectsLeftToBatch.delete(projectName); - } - } - batches.push(workspaceBatch); - } - while (projectsLeftToBatch.size > 0) { - // Get all projects that have no remaining dependencies within the repo - // that haven't yet been picked. - const batch = []; - for (const projectName of projectsLeftToBatch) { - const projectDeps = projectGraph.get(projectName); - const needsDependenciesBatched = projectDeps.some(dep => projectsLeftToBatch.has(dep.name)); - if (!needsDependenciesBatched) { - batch.push(projectsToBatch.get(projectName)); - } - } - // If we weren't able to find a project with no remaining dependencies, - // then we've encountered a cycle in the dependency graph. - const hasCycles = batch.length === 0; - if (hasCycles) { - const cycleProjectNames = [...projectsLeftToBatch]; - const message = 'Encountered a cycle in the dependency graph. Projects in cycle are:\n' + cycleProjectNames.join(', '); - throw new _errors.CliError(message); - } - batches.push(batch); - batch.forEach(project => projectsLeftToBatch.delete(project.name)); - } - return batches; -} -function includeTransitiveProjects(subsetOfProjects, allProjects, { onlyProductionDependencies = false } = {}) { - const dependentProjects = new Map(); - // the current list of packages we are expanding using breadth-first-search - const toProcess = [...subsetOfProjects]; - while (toProcess.length > 0) { - const project = toProcess.shift(); - const dependencies = onlyProductionDependencies ? project.productionDependencies : project.allDependencies; - Object.keys(dependencies).forEach(dep => { - if (allProjects.has(dep)) { - toProcess.push(allProjects.get(dep)); - } - }); - dependentProjects.set(project.name, project); + if (!needsDependenciesBatched) { + batch.push(projectsToBatch.get(projectName)); + } + } // If we weren't able to find a project with no remaining dependencies, + // then we've encountered a cycle in the dependency graph. + + + const hasCycles = batch.length === 0; + + if (hasCycles) { + const cycleProjectNames = [...projectsLeftToBatch]; + const message = 'Encountered a cycle in the dependency graph. Projects in cycle are:\n' + cycleProjectNames.join(', '); + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](message); } - return dependentProjects; + + batches.push(batch); + batch.forEach(project => projectsLeftToBatch.delete(project.name)); + } + + return batches; +} +function includeTransitiveProjects(subsetOfProjects, allProjects, { + onlyProductionDependencies = false +} = {}) { + const dependentProjects = new Map(); // the current list of packages we are expanding using breadth-first-search + + const toProcess = [...subsetOfProjects]; + + while (toProcess.length > 0) { + const project = toProcess.shift(); + const dependencies = onlyProductionDependencies ? project.productionDependencies : project.allDependencies; + Object.keys(dependencies).forEach(dep => { + if (allProjects.has(dep)) { + toProcess.push(allProjects.get(dep)); + } + }); + dependentProjects.set(project.name, project); + } + + return dependentProjects; } /***/ }), @@ -7854,14 +7782,11 @@ function onceStrict (fn) { /***/ }), /* 52 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CliError", function() { return CliError; }); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -7881,208 +7806,227 @@ Object.defineProperty(exports, "__esModule", { * under the License. */ class CliError extends Error { - constructor(message, meta = {}) { - super(message); - this.meta = meta; - } + constructor(message, meta = {}) { + super(message); + this.meta = meta; + } + } -exports.CliError = CliError; /***/ }), /* 53 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return Project; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(33); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(54); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(92); +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Project = undefined; -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* - * 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. - */ -var _chalk = __webpack_require__(2); -var _chalk2 = _interopRequireDefault(_chalk); -var _path = __webpack_require__(16); -var _util = __webpack_require__(29); +class Project { + static async fromPath(path) { + const pkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(path); + return new Project(pkgJson, path); + } -var _errors = __webpack_require__(52); + constructor(packageJson, projectPath) { + _defineProperty(this, "json", void 0); -var _log = __webpack_require__(33); + _defineProperty(this, "packageJsonLocation", void 0); -var _package_json = __webpack_require__(54); + _defineProperty(this, "nodeModulesLocation", void 0); -var _scripts = __webpack_require__(92); + _defineProperty(this, "targetLocation", void 0); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + _defineProperty(this, "path", void 0); -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + _defineProperty(this, "allDependencies", void 0); -class Project { - constructor(packageJson, projectPath) { - this.isWorkspaceRoot = false; - this.isWorkspaceProject = false; - this.json = Object.freeze(packageJson); - this.path = projectPath; - this.packageJsonLocation = (0, _path.resolve)(this.path, 'package.json'); - this.nodeModulesLocation = (0, _path.resolve)(this.path, 'node_modules'); - this.targetLocation = (0, _path.resolve)(this.path, 'target'); - this.productionDependencies = this.json.dependencies || {}; - this.devDependencies = this.json.devDependencies || {}; - this.allDependencies = _extends({}, this.devDependencies, this.productionDependencies); - this.isWorkspaceRoot = this.json.hasOwnProperty('workspaces'); - this.scripts = this.json.scripts || {}; - } - static fromPath(path) { - return _asyncToGenerator(function* () { - const pkgJson = yield (0, _package_json.readPackageJson)(path); - return new Project(pkgJson, path); - })(); - } - get name() { - return this.json.name; - } - ensureValidProjectDependency(project, dependentProjectIsInWorkspace) { - const versionInPackageJson = this.allDependencies[project.name]; - let expectedVersionInPackageJson; - if (dependentProjectIsInWorkspace) { - expectedVersionInPackageJson = project.json.version; - } else { - const relativePathToProject = normalizePath((0, _path.relative)(this.path, project.path)); - expectedVersionInPackageJson = `link:${relativePathToProject}`; - } - // No issues! - if (versionInPackageJson === expectedVersionInPackageJson) { - return; - } - let problemMsg; - if ((0, _package_json.isLinkDependency)(versionInPackageJson) && dependentProjectIsInWorkspace) { - problemMsg = `but should be using a workspace`; - } else if ((0, _package_json.isLinkDependency)(versionInPackageJson)) { - problemMsg = `using 'link:', but the path is wrong`; - } else { - problemMsg = `but it's not using the local package`; - } - throw new _errors.CliError(`[${this.name}] depends on [${project.name}] ${problemMsg}. Update its package.json to the expected value below.`, { - actual: `"${project.name}": "${versionInPackageJson}"`, - expected: `"${project.name}": "${expectedVersionInPackageJson}"`, - package: `${this.name} (${this.packageJsonLocation})` - }); - } - getBuildConfig() { - return this.json.kibana && this.json.kibana.build || {}; - } - /** - * Returns the directory that should be copied into the Kibana build artifact. - * This config can be specified to only include the project's build artifacts - * instead of everything located in the project directory. - */ - getIntermediateBuildDirectory() { - return (0, _path.resolve)(this.path, this.getBuildConfig().intermediateBuildDirectory || '.'); - } - getCleanConfig() { - return this.json.kibana && this.json.kibana.clean || {}; - } - hasScript(name) { - return name in this.scripts; - } - getExecutables() { - const raw = this.json.bin; - if (!raw) { - return {}; - } - if (typeof raw === 'string') { - return { - [this.name]: (0, _path.resolve)(this.path, raw) - }; - } - if (typeof raw === 'object') { - const binsConfig = {}; - for (const binName of Object.keys(raw)) { - binsConfig[binName] = (0, _path.resolve)(this.path, raw[binName]); - } - return binsConfig; - } - throw new _errors.CliError(`[${this.name}] has an invalid "bin" field in its package.json, ` + `expected an object or a string`, { - binConfig: (0, _util.inspect)(raw), - package: `${this.name} (${this.packageJsonLocation})` - }); - } - runScript(scriptName, args = []) { - var _this = this; + _defineProperty(this, "productionDependencies", void 0); + + _defineProperty(this, "devDependencies", void 0); + + _defineProperty(this, "scripts", void 0); + + _defineProperty(this, "isWorkspaceRoot", false); + + _defineProperty(this, "isWorkspaceProject", false); + + this.json = Object.freeze(packageJson); + this.path = projectPath; + this.packageJsonLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'package.json'); + this.nodeModulesLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'node_modules'); + this.targetLocation = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, 'target'); + this.productionDependencies = this.json.dependencies || {}; + this.devDependencies = this.json.devDependencies || {}; + this.allDependencies = _objectSpread({}, this.devDependencies, this.productionDependencies); + this.isWorkspaceRoot = this.json.hasOwnProperty('workspaces'); + this.scripts = this.json.scripts || {}; + } + + get name() { + return this.json.name; + } + + ensureValidProjectDependency(project, dependentProjectIsInWorkspace) { + const versionInPackageJson = this.allDependencies[project.name]; + let expectedVersionInPackageJson; - return _asyncToGenerator(function* () { - _log.log.write(_chalk2.default.bold(`\n\nRunning script [${_chalk2.default.green(scriptName)}] in [${_chalk2.default.green(_this.name)}]:\n`)); - return (0, _scripts.runScriptInPackage)(scriptName, args, _this); - })(); + if (dependentProjectIsInWorkspace) { + expectedVersionInPackageJson = project.json.version; + } else { + const relativePathToProject = normalizePath(Object(path__WEBPACK_IMPORTED_MODULE_1__["relative"])(this.path, project.path)); + expectedVersionInPackageJson = `link:${relativePathToProject}`; + } // No issues! + + + if (versionInPackageJson === expectedVersionInPackageJson) { + return; } - runScriptStreaming(scriptName, args = []) { - return (0, _scripts.runScriptInPackageStreaming)(scriptName, args, this); + + let problemMsg; + + if (Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["isLinkDependency"])(versionInPackageJson) && dependentProjectIsInWorkspace) { + problemMsg = `but should be using a workspace`; + } else if (Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["isLinkDependency"])(versionInPackageJson)) { + problemMsg = `using 'link:', but the path is wrong`; + } else { + problemMsg = `but it's not using the local package`; } - hasDependencies() { - return Object.keys(this.allDependencies).length > 0; + + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`[${this.name}] depends on [${project.name}] ${problemMsg}. Update its package.json to the expected value below.`, { + actual: `"${project.name}": "${versionInPackageJson}"`, + expected: `"${project.name}": "${expectedVersionInPackageJson}"`, + package: `${this.name} (${this.packageJsonLocation})` + }); + } + + getBuildConfig() { + return this.json.kibana && this.json.kibana.build || {}; + } + /** + * Returns the directory that should be copied into the Kibana build artifact. + * This config can be specified to only include the project's build artifacts + * instead of everything located in the project directory. + */ + + + getIntermediateBuildDirectory() { + return Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, this.getBuildConfig().intermediateBuildDirectory || '.'); + } + + getCleanConfig() { + return this.json.kibana && this.json.kibana.clean || {}; + } + + hasScript(name) { + return name in this.scripts; + } + + getExecutables() { + const raw = this.json.bin; + + if (!raw) { + return {}; } - installDependencies({ extraArgs }) { - var _this2 = this; - return _asyncToGenerator(function* () { - _log.log.write(_chalk2.default.bold(`\n\nInstalling dependencies in [${_chalk2.default.green(_this2.name)}]:\n`)); - return (0, _scripts.installInDir)(_this2.path, extraArgs); - })(); + if (typeof raw === 'string') { + return { + [this.name]: Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, raw) + }; } -} -exports.Project = Project; // We normalize all path separators to `/` in generated files -function normalizePath(path) { - return path.replace(/[\\\/]+/g, '/'); -} + if (typeof raw === 'object') { + const binsConfig = {}; -/***/ }), -/* 54 */ -/***/ (function(module, exports, __webpack_require__) { + for (const binName of Object.keys(raw)) { + binsConfig[binName] = Object(path__WEBPACK_IMPORTED_MODULE_1__["resolve"])(this.path, raw[binName]); + } -"use strict"; + return binsConfig; + } + + throw new _errors__WEBPACK_IMPORTED_MODULE_3__["CliError"](`[${this.name}] has an invalid "bin" field in its package.json, ` + `expected an object or a string`, { + binConfig: Object(util__WEBPACK_IMPORTED_MODULE_2__["inspect"])(raw), + package: `${this.name} (${this.packageJsonLocation})` + }); + } + async runScript(scriptName, args = []) { + _log__WEBPACK_IMPORTED_MODULE_4__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\n\nRunning script [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(scriptName)}] in [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(this.name)}]:\n`)); + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["runScriptInPackage"])(scriptName, args, this); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isLinkDependency = undefined; -exports.readPackageJson = readPackageJson; -exports.writePackageJson = writePackageJson; + runScriptStreaming(scriptName, args = []) { + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["runScriptInPackageStreaming"])(scriptName, args, this); + } -var _readPkg = __webpack_require__(55); + hasDependencies() { + return Object.keys(this.allDependencies).length > 0; + } -var _readPkg2 = _interopRequireDefault(_readPkg); + async installDependencies({ + extraArgs + }) { + _log__WEBPACK_IMPORTED_MODULE_4__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\n\nInstalling dependencies in [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(this.name)}]:\n`)); + return Object(_scripts__WEBPACK_IMPORTED_MODULE_6__["installInDir"])(this.path, extraArgs); + } -var _writePkg = __webpack_require__(82); +} // We normalize all path separators to `/` in generated files -var _writePkg2 = _interopRequireDefault(_writePkg); +function normalizePath(path) { + return path.replace(/[\\\/]+/g, '/'); +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/***/ }), +/* 54 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readPackageJson", function() { return readPackageJson; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writePackageJson", function() { return writePackageJson; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; }); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(82); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8101,13 +8045,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * specific language governing permissions and limitations * under the License. */ + + function readPackageJson(dir) { - return (0, _readPkg2.default)(dir, { normalize: false }); + return read_pkg__WEBPACK_IMPORTED_MODULE_0___default()(dir, { + normalize: false + }); } function writePackageJson(path, json) { - return (0, _writePkg2.default)(path, json); + return write_pkg__WEBPACK_IMPORTED_MODULE_1___default()(path, json); } -const isLinkDependency = exports.isLinkDependency = depVersion => depVersion.startsWith('link:'); +const isLinkDependency = depVersion => depVersion.startsWith('link:'); /***/ }), /* 55 */ @@ -13496,165 +13444,141 @@ module.exports = str => { /***/ }), /* 92 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installInDir", function() { return installInDir; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(93); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.runScriptInPackage = exports.installInDir = undefined; - /** * Install all dependencies in the given directory */ -let installInDir = exports.installInDir = (() => { - var _ref = _asyncToGenerator(function* (directory, extraArgs = []) { - const options = ['install', '--non-interactive', ...extraArgs]; - // We pass the mutex flag to ensure only one instance of yarn runs at any - // given time (e.g. to avoid conflicts). - yield (0, _child_process.spawn)('yarn', options, { - cwd: directory - }); - }); +async function installInDir(directory, extraArgs = []) { + const options = ['install', '--non-interactive', ...extraArgs]; // We pass the mutex flag to ensure only one instance of yarn runs at any + // given time (e.g. to avoid conflicts). - return function installInDir(_x) { - return _ref.apply(this, arguments); - }; -})(); + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', options, { + cwd: directory + }); +} /** * Run script in the given directory */ - -let runScriptInPackage = exports.runScriptInPackage = (() => { - var _ref2 = _asyncToGenerator(function* (script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - yield (0, _child_process.spawn)('yarn', ['run', script, ...args], execOpts); - }); - - return function runScriptInPackage(_x2, _x3, _x4) { - return _ref2.apply(this, arguments); - }; -})(); +async function runScriptInPackage(script, args, pkg) { + const execOpts = { + cwd: pkg.path + }; + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['run', script, ...args], execOpts); +} /** * Run script in the given directory */ - -exports.runScriptInPackageStreaming = runScriptInPackageStreaming; - -var _child_process = __webpack_require__(93); - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ - - function runScriptInPackageStreaming(script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - return (0, _child_process.spawnStreaming)('yarn', ['run', script, ...args], execOpts, { - prefix: pkg.name - }); + const execOpts = { + cwd: pkg.path + }; + return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])('yarn', ['run', script, ...args], execOpts, { + prefix: pkg.name + }); } /***/ }), /* 93 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawn", function() { return spawn; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawnStreaming", function() { return spawnStreaming; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(94); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(122); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(123); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* - * 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. - */ - - -exports.spawn = spawn; -exports.spawnStreaming = spawnStreaming; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _execa = __webpack_require__(94); - -var _execa2 = _interopRequireDefault(_execa); - -var _logSymbols = __webpack_require__(122); - -var _logSymbols2 = _interopRequireDefault(_logSymbols); -var _strongLogTransformer = __webpack_require__(123); -var _strongLogTransformer2 = _interopRequireDefault(_strongLogTransformer); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function generateColors() { - const colorWheel = [_chalk2.default.cyan, _chalk2.default.magenta, _chalk2.default.blue, _chalk2.default.yellow, _chalk2.default.green]; - const count = colorWheel.length; - let children = 0; - return () => colorWheel[children++ % count]; + const colorWheel = [chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.magenta, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.blue, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green]; + const count = colorWheel.length; + let children = 0; + return () => colorWheel[children++ % count]; } + function spawn(command, args, opts) { - return (0, _execa2.default)(command, args, _extends({}, opts, { - stdio: 'inherit' - })); + return execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({}, opts, { + stdio: 'inherit' + })); } const nextColor = generateColors(); -function spawnStreaming(command, args, opts, { prefix }) { - const spawned = (0, _execa2.default)(command, args, _extends({}, opts, { - stdio: ['ignore', 'pipe', 'pipe'] - })); - const color = nextColor(); - const prefixedStdout = (0, _strongLogTransformer2.default)({ tag: `${color.bold(prefix)}:` }); - const prefixedStderr = (0, _strongLogTransformer2.default)({ - mergeMultiline: true, - tag: `${_logSymbols2.default.error} ${color.bold(prefix)}:` - }); - spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); - spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); - return spawned; +function spawnStreaming(command, args, opts, { + prefix +}) { + const spawned = execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({}, opts, { + stdio: ['ignore', 'pipe', 'pipe'] + })); + const color = nextColor(); + const prefixedStdout = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + tag: `${color.bold(prefix)}:` + }); + const prefixedStderr = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + mergeMultiline: true, + tag: `${log_symbols__WEBPACK_IMPORTED_MODULE_2___default.a.error} ${color.bold(prefix)}:` + }); + spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); + spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); + return spawned; } /***/ }), @@ -17429,306 +17353,290 @@ module.exports = {"name":"strong-log-transformer","version":"2.1.0","description /***/ }), /* 131 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; }); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(54); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.copyWorkspacePackages = exports.workspacePackagePaths = undefined; - -let workspacePackagePaths = exports.workspacePackagePaths = (() => { - var _ref = _asyncToGenerator(function* (rootPath) { - const rootPkgJson = yield (0, _package_json.readPackageJson)(_path2.default.join(rootPath, 'package.json')); - if (!rootPkgJson.workspaces) { - return []; - } - const workspacesPathsPatterns = rootPkgJson.workspaces.packages; - let workspaceProjectsPaths = []; - for (const pattern of workspacesPathsPatterns) { - workspaceProjectsPaths = workspaceProjectsPaths.concat((yield packagesFromGlobPattern({ pattern, rootPath }))); - } - // Filter out exclude glob patterns - for (const pattern of workspacesPathsPatterns) { - if (pattern.startsWith('!')) { - const pathToRemove = _path2.default.join(rootPath, pattern.slice(1), 'package.json'); - workspaceProjectsPaths = workspaceProjectsPaths.filter(function (p) { - return p !== pathToRemove; - }); - } - } - return workspaceProjectsPaths; - }); - return function workspacePackagePaths(_x) { - return _ref.apply(this, arguments); - }; -})(); -let copyWorkspacePackages = exports.copyWorkspacePackages = (() => { - var _ref2 = _asyncToGenerator(function* (rootPath) { - const workspaceProjects = yield getWorkspaceProjects(rootPath); - for (const project of workspaceProjects.values()) { - const dest = _path2.default.resolve(rootPath, 'node_modules', project.name); - // Remove the symlink - yield (0, _fs.unlink)(dest); - // Copy in the package - yield (0, _fs.copyDirectory)(project.path, dest); - } - }); - return function copyWorkspacePackages(_x2) { - return _ref2.apply(this, arguments); - }; -})(); - -let getWorkspaceProjects = (() => { - var _ref3 = _asyncToGenerator(function* (rootPath) { - const projectPaths = (0, _config.getProjectPaths)(rootPath, {}); - const projects = yield (0, _projects.getProjects)(rootPath, projectPaths); - for (const [key, project] of projects.entries()) { - if (!project.isWorkspaceProject) { - projects.delete(key); - } - } - return projects; - }); - return function getWorkspaceProjects(_x3) { - return _ref3.apply(this, arguments); - }; -})(); -var _glob = __webpack_require__(36); +const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); +async function workspacePackagePaths(rootPath) { + const rootPkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, 'package.json')); -var _glob2 = _interopRequireDefault(_glob); + if (!rootPkgJson.workspaces) { + return []; + } -var _path = __webpack_require__(16); + const workspacesPathsPatterns = rootPkgJson.workspaces.packages; + let workspaceProjectsPaths = []; -var _path2 = _interopRequireDefault(_path); + for (const pattern of workspacesPathsPatterns) { + workspaceProjectsPaths = workspaceProjectsPaths.concat((await packagesFromGlobPattern({ + pattern, + rootPath + }))); + } // Filter out exclude glob patterns -var _util = __webpack_require__(29); -var _config = __webpack_require__(132); + for (const pattern of workspacesPathsPatterns) { + if (pattern.startsWith('!')) { + const pathToRemove = path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, pattern.slice(1), 'package.json'); + workspaceProjectsPaths = workspaceProjectsPaths.filter(p => p !== pathToRemove); + } + } -var _fs = __webpack_require__(20); + return workspaceProjectsPaths; +} +async function copyWorkspacePackages(rootPath) { + const workspaceProjects = await getWorkspaceProjects(rootPath); -var _package_json = __webpack_require__(54); + for (const project of workspaceProjects.values()) { + const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); // Remove the symlink -var _projects = __webpack_require__(35); + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); + } +} -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ +async function getWorkspaceProjects(rootPath) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(rootPath, {}); + const projects = await Object(_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(rootPath, projectPaths); + for (const [key, project] of projects.entries()) { + if (!project.isWorkspaceProject) { + projects.delete(key); + } + } -const glob = (0, _util.promisify)(_glob2.default); + return projects; +} -function packagesFromGlobPattern({ pattern, rootPath }) { - const globOptions = { - cwd: rootPath, - // Should throw in case of unusual errors when reading the file system - strict: true, - // Always returns absolute paths for matched files - absolute: true, - // Do not match ** against multiple filenames - // (This is only specified because we currently don't have a need for it.) - noglobstar: true - }; - return glob(_path2.default.join(pattern, 'package.json'), globOptions); +function packagesFromGlobPattern({ + pattern, + rootPath +}) { + const globOptions = { + cwd: rootPath, + // Should throw in case of unusual errors when reading the file system + strict: true, + // Always returns absolute paths for matched files + absolute: true, + // Do not match ** against multiple filenames + // (This is only specified because we currently don't have a need for it.) + noglobstar: true + }; + return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); } /***/ }), /* 132 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return getProjectPaths; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getProjectPaths = getProjectPaths; - -var _path = __webpack_require__(16); - /** * Returns all the paths where plugins are located */ function getProjectPaths(rootPath, options) { - const skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); - const ossOnly = Boolean(options.oss); - const projectPaths = [rootPath, (0, _path.resolve)(rootPath, 'packages/*')]; - // This is needed in order to install the dependencies for the declared - // plugin functional used in the selenium functional tests. - // As we are now using the webpack dll for the client vendors dependencies - // when we run the plugin functional tests against the distributable - // dependencies used by such plugins like @eui, react and react-dom can't - // be loaded from the dll as the context is different from the one declared - // into the webpack dll reference plugin. - // In anyway, have a plugin declaring their own dependencies is the - // correct and the expect behavior. - projectPaths.push((0, _path.resolve)(rootPath, 'test/plugin_functional/plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'test/interpreter_functional/plugins/*')); - if (!ossOnly) { - projectPaths.push((0, _path.resolve)(rootPath, 'x-pack')); - projectPaths.push((0, _path.resolve)(rootPath, 'x-pack/plugins/*')); - } - if (!skipKibanaPlugins) { - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*')); - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*/packages/*')); - projectPaths.push((0, _path.resolve)(rootPath, '../kibana-extra/*/plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*/packages/*')); - projectPaths.push((0, _path.resolve)(rootPath, 'plugins/*/plugins/*')); - } - return projectPaths; -} /* - * 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 skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); + const ossOnly = Boolean(options.oss); + const projectPaths = [rootPath, Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'packages/*')]; // This is needed in order to install the dependencies for the declared + // plugin functional used in the selenium functional tests. + // As we are now using the webpack dll for the client vendors dependencies + // when we run the plugin functional tests against the distributable + // dependencies used by such plugins like @eui, react and react-dom can't + // be loaded from the dll as the context is different from the one declared + // into the webpack dll reference plugin. + // In anyway, have a plugin declaring their own dependencies is the + // correct and the expect behavior. -/***/ }), -/* 133 */ -/***/ (function(module, exports, __webpack_require__) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/plugin_functional/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/interpreter_functional/plugins/*')); -"use strict"; + if (!ossOnly) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*')); + } + if (!skipKibanaPlugins) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/plugins/*')); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.CleanCommand = undefined; + return projectPaths; +} -var _chalk = __webpack_require__(2); +/***/ }), +/* 133 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -var _chalk2 = _interopRequireDefault(_chalk); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(148); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(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. + */ -var _del = __webpack_require__(134); -var _del2 = _interopRequireDefault(_del); -var _ora = __webpack_require__(148); -var _ora2 = _interopRequireDefault(_ora); -var _path = __webpack_require__(16); -var _fs = __webpack_require__(20); +const CleanCommand = { + description: 'Remove the node_modules and target directories from all projects.', + name: 'clean', -var _log = __webpack_require__(33); + async run(projects) { + const toDelete = []; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + for (const project of projects.values()) { + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.nodeModulesLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.nodeModulesLocation) + }); + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.targetLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.targetLocation) + }); + } + const { + extraPatterns + } = project.getCleanConfig(); -const CleanCommand = exports.CleanCommand = { - description: 'Remove the node_modules and target directories from all projects.', - name: 'clean', - run(projects) { - return _asyncToGenerator(function* () { - const toDelete = []; - for (const project of projects.values()) { - if (yield (0, _fs.isDirectory)(project.nodeModulesLocation)) { - toDelete.push({ - cwd: project.path, - pattern: (0, _path.relative)(project.path, project.nodeModulesLocation) - }); - } - if (yield (0, _fs.isDirectory)(project.targetLocation)) { - toDelete.push({ - cwd: project.path, - pattern: (0, _path.relative)(project.path, project.targetLocation) - }); - } - const { extraPatterns } = project.getCleanConfig(); - if (extraPatterns) { - toDelete.push({ - cwd: project.path, - pattern: extraPatterns - }); - } - } - if (toDelete.length === 0) { - _log.log.write(_chalk2.default.bold.green('\n\nNothing to delete')); - } else { - _log.log.write(_chalk2.default.bold.red('\n\nDeleting:\n')); - /** - * In order to avoid patterns like `/build` in packages from accidentally - * impacting files outside the package we use `process.chdir()` to change - * the cwd to the package and execute `del()` without the `force` option - * so it will check that each file being deleted is within the package. - * - * `del()` does support a `cwd` option, but it's only for resolving the - * patterns and does not impact the cwd check. - */ - const originalCwd = process.cwd(); - try { - for (const _ref of toDelete) { - const { pattern, cwd } = _ref; + if (extraPatterns) { + toDelete.push({ + cwd: project.path, + pattern: extraPatterns + }); + } + } - process.chdir(cwd); - const promise = (0, _del2.default)(pattern); - _ora2.default.promise(promise, (0, _path.relative)(originalCwd, (0, _path.join)(cwd, String(pattern)))); - yield promise; - } - } finally { - process.chdir(originalCwd); - } - } - })(); + if (toDelete.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.green('\n\nNothing to delete')); + } else { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red('\n\nDeleting:\n')); + /** + * In order to avoid patterns like `/build` in packages from accidentally + * impacting files outside the package we use `process.chdir()` to change + * the cwd to the package and execute `del()` without the `force` option + * so it will check that each file being deleted is within the package. + * + * `del()` does support a `cwd` option, but it's only for resolving the + * patterns and does not impact the cwd check. + */ + + const originalCwd = process.cwd(); + + try { + for (const _ref of toDelete) { + const { + pattern, + cwd + } = _ref; + process.chdir(cwd); + const promise = del__WEBPACK_IMPORTED_MODULE_1___default()(pattern); + ora__WEBPACK_IMPORTED_MODULE_2___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_3__["join"])(cwd, String(pattern)))); + await promise; + } + } finally { + process.chdir(originalCwd); + } } + } + }; /***/ }), @@ -19288,120 +19196,99 @@ module.exports = {"dots":{"interval":80,"frames":["⠋","⠙","⠹","⠸","⠼", /***/ }), /* 155 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.RunCommand = undefined; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _log = __webpack_require__(33); - -var _parallelize = __webpack_require__(34); - -var _projects = __webpack_require__(35); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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 RunCommand = exports.RunCommand = { - description: 'Run script defined in package.json in each package that contains that script.', - name: 'run', - run(projects, projectGraph, { extraArgs }) { - return _asyncToGenerator(function* () { - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - if (extraArgs.length === 0) { - _log.log.write(_chalk2.default.red.bold('\nNo script specified')); - process.exit(1); - } - const scriptName = extraArgs[0]; - const scriptArgs = extraArgs.slice(1); - _log.log.write(_chalk2.default.bold(`\nRunning script [${_chalk2.default.green(scriptName)}] in batched topological order\n`)); - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - if (pkg.hasScript(scriptName)) { - yield pkg.runScriptStreaming(scriptName, scriptArgs); - } - }); - - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - })(); - } -}; -/***/ }), -/* 156 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; +const RunCommand = { + description: 'Run script defined in package.json in each package that contains that script.', + name: 'run', + async run(projects, projectGraph, { + extraArgs + }) { + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WatchCommand = undefined; + if (extraArgs.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red.bold('\nNo script specified')); + process.exit(1); + } -var _chalk = __webpack_require__(2); + const scriptName = extraArgs[0]; + const scriptArgs = extraArgs.slice(1); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`\nRunning script [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(scriptName)}] in batched topological order\n`)); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { + if (pkg.hasScript(scriptName)) { + await pkg.runScriptStreaming(scriptName, scriptArgs); + } + }); + } -var _chalk2 = _interopRequireDefault(_chalk); +}; -var _log = __webpack_require__(33); +/***/ }), +/* 156 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -var _parallelize = __webpack_require__(34); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(157); +/* + * 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. + */ -var _projects = __webpack_require__(35); -var _watch = __webpack_require__(157); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ /** @@ -19411,6 +19298,7 @@ const watchScriptName = 'kbn:watch'; /** * Name of the Kibana project. */ + const kibanaProjectName = 'kibana'; /** * Command that traverses through list of available projects/packages that have `kbn:watch` script in their @@ -19422,68 +19310,54 @@ const kibanaProjectName = 'kibana'; * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for * `webpack` and `tsc` only, for the rest we rely on predefined timeouts. */ -const WatchCommand = exports.WatchCommand = { - description: 'Runs `kbn:watch` script for every project.', - name: 'watch', - run(projects, projectGraph) { - return _asyncToGenerator(function* () { - const projectsToWatch = new Map(); - for (const project of projects.values()) { - // We can't watch project that doesn't have `kbn:watch` script. - if (project.hasScript(watchScriptName)) { - projectsToWatch.set(project.name, project); - } - } - if (projectsToWatch.size === 0) { - _log.log.write(_chalk2.default.red(`\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n`)); - return; - } - const projectNames = Array.from(projectsToWatch.keys()); - _log.log.write(_chalk2.default.bold(_chalk2.default.green(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`))); - // Kibana should always be run the last, so we don't rely on automatic - // topological batching and push it to the last one-entry batch manually. - const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projectsToWatch, projectGraph); - if (shouldWatchKibanaProject) { - batchedProjects.push([projects.get(kibanaProjectName)]); - } - yield (0, _parallelize.parallelizeBatches)(batchedProjects, (() => { - var _ref = _asyncToGenerator(function* (pkg) { - const completionHint = yield (0, _watch.waitUntilWatchIsReady)(pkg.runScriptStreaming(watchScriptName).stdout); - _log.log.write(_chalk2.default.bold(`[${_chalk2.default.green(pkg.name)}] Initial build completed (${completionHint}).`)); - }); - return function (_x) { - return _ref.apply(this, arguments); - }; - })()); - })(); - } -}; +const WatchCommand = { + description: 'Runs `kbn:watch` script for every project.', + name: 'watch', -/***/ }), -/* 157 */ -/***/ (function(module, exports, __webpack_require__) { + async run(projects, projectGraph) { + const projectsToWatch = new Map(); -"use strict"; + for (const project of projects.values()) { + // We can't watch project that doesn't have `kbn:watch` script. + if (project.hasScript(watchScriptName)) { + projectsToWatch.set(project.name, project); + } + } + if (projectsToWatch.size === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n`)); + return; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.waitUntilWatchIsReady = waitUntilWatchIsReady; + const projectNames = Array.from(projectsToWatch.keys()); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`))); // Kibana should always be run the last, so we don't rely on automatic + // topological batching and push it to the last one-entry batch manually. -var _rxjs = __webpack_require__(158); + const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projectsToWatch, projectGraph); -var Rx = _interopRequireWildcard(_rxjs); + if (shouldWatchKibanaProject) { + batchedProjects.push([projects.get(kibanaProjectName)]); + } -var _operators = __webpack_require__(257); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { + const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_4__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName).stdout); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`[${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(pkg.name)}] Initial build completed (${completionHint}).`)); + }); + } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } +}; -/** - * Number of milliseconds we wait before we fall back to the default watch handler. - */ +/***/ }), +/* 157 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(158); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19502,27 +19376,46 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; * specific language governing permissions and limitations * under the License. */ + + +/** + * Number of milliseconds we wait before we fall back to the default watch handler. + */ + const defaultHandlerDelay = 3000; /** * If default watch handler is used, then it's the number of milliseconds we wait for * any build output before we consider watch task ready. */ + const defaultHandlerReadinessTimeout = 2000; -function getWatchHandlers(buildOutput$, { handlerDelay = defaultHandlerDelay, handlerReadinessTimeout = defaultHandlerReadinessTimeout }) { - const typescriptHandler = buildOutput$.pipe((0, _operators.first)(data => data.includes('$ tsc')), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.first)(data => data.includes('Compilation complete.')), (0, _operators.mapTo)('tsc')))); - const webpackHandler = buildOutput$.pipe((0, _operators.first)(data => data.includes('$ webpack')), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.first)(data => data.includes('Chunk Names')), (0, _operators.mapTo)('webpack')))); - const defaultHandler = Rx.of(undefined).pipe((0, _operators.delay)(handlerReadinessTimeout), (0, _operators.map)(() => buildOutput$.pipe((0, _operators.timeout)(handlerDelay), (0, _operators.catchError)(() => Rx.of('timeout'))))); +/** + * Describes configurable watch options. + */ + +function getWatchHandlers(buildOutput$, { + handlerDelay = defaultHandlerDelay, + handlerReadinessTimeout = defaultHandlerReadinessTimeout +}) { + const typescriptHandler = buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('$ tsc')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('Compilation complete.')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mapTo"])('tsc')))); + const webpackHandler = buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('$ webpack')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["first"])(data => data.includes('Chunk Names')), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mapTo"])('webpack')))); + const defaultHandler = rxjs__WEBPACK_IMPORTED_MODULE_0__["of"](undefined).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["delay"])(handlerReadinessTimeout), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["map"])(() => buildOutput$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["timeout"])(handlerDelay), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["catchError"])(() => rxjs__WEBPACK_IMPORTED_MODULE_0__["of"]('timeout'))))); return [typescriptHandler, webpackHandler, defaultHandler]; } + function waitUntilWatchIsReady(stream, opts = {}) { - const buildOutput$ = new Rx.Subject(); + const buildOutput$ = new rxjs__WEBPACK_IMPORTED_MODULE_0__["Subject"](); + const onDataListener = data => buildOutput$.next(data.toString('utf-8')); + const onEndListener = () => buildOutput$.complete(); + const onErrorListener = e => buildOutput$.error(e); + stream.once('end', onEndListener); stream.once('error', onErrorListener); stream.on('data', onDataListener); - return Rx.race(getWatchHandlers(buildOutput$, opts)).pipe((0, _operators.mergeMap)(whenReady => whenReady), (0, _operators.finalize)(() => { + return rxjs__WEBPACK_IMPORTED_MODULE_0__["race"](getWatchHandlers(buildOutput$, opts)).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["mergeMap"])(whenReady => whenReady), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_1__["finalize"])(() => { stream.removeListener('data', onDataListener); stream.removeListener('end', onEndListener); stream.removeListener('error', onErrorListener); @@ -31110,108 +31003,96 @@ function zipAll(project) { /***/ }), /* 357 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(358); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(359); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(52); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(35); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(366); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.runCommand = undefined; - -let runCommand = exports.runCommand = (() => { - var _ref = _asyncToGenerator(function* (command, config) { - try { - _log.log.write(_chalk2.default.bold(`Running [${_chalk2.default.green(command.name)}] command from [${_chalk2.default.yellow(config.rootPath)}]:\n`)); - const projectPaths = (0, _config.getProjectPaths)(config.rootPath, config.options); - const projects = yield (0, _projects.getProjects)(config.rootPath, projectPaths, { - exclude: toArray(config.options.exclude), - include: toArray(config.options.include) - }); - if (projects.size === 0) { - _log.log.write(_chalk2.default.red(`There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n`)); - return process.exit(1); - } - const projectGraph = (0, _projects.buildProjectGraph)(projects); - _log.log.write(_chalk2.default.bold(`Found [${_chalk2.default.green(projects.size.toString())}] projects:\n`)); - _log.log.write((0, _projects_tree.renderProjectsTree)(config.rootPath, projects)); - yield command.run(projects, projectGraph, config); - } catch (e) { - _log.log.write(_chalk2.default.bold.red(`\n[${command.name}] failed:\n`)); - if (e instanceof _errors.CliError) { - const msg = _chalk2.default.red(`CliError: ${e.message}\n`); - _log.log.write((0, _wrapAnsi2.default)(msg, 80)); - const keys = Object.keys(e.meta); - if (keys.length > 0) { - const metaOutput = keys.map(function (key) { - const value = e.meta[key]; - return `${key}: ${value}`; - }); - _log.log.write('Additional debugging info:\n'); - _log.log.write((0, _indentString2.default)(metaOutput.join('\n'), 3)); - } - } else { - _log.log.write(e.stack); - } - process.exit(1); - } - }); - - return function runCommand(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _indentString = __webpack_require__(358); -var _indentString2 = _interopRequireDefault(_indentString); -var _wrapAnsi = __webpack_require__(359); -var _wrapAnsi2 = _interopRequireDefault(_wrapAnsi); -var _config = __webpack_require__(132); -var _errors = __webpack_require__(52); -var _log = __webpack_require__(33); +async function runCommand(command, config) { + try { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`Running [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(command.name)}] command from [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow(config.rootPath)}]:\n`)); + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(config.rootPath, config.options); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(config.rootPath, projectPaths, { + exclude: toArray(config.options.exclude), + include: toArray(config.options.include) + }); -var _projects = __webpack_require__(35); + if (projects.size === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n`)); + return process.exit(1); + } -var _projects_tree = __webpack_require__(366); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_6__["buildProjectGraph"])(projects); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold(`Found [${chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(projects.size.toString())}] projects:\n`)); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(Object(_utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__["renderProjectsTree"])(config.rootPath, projects)); + await command.run(projects, projectGraph, config); + } catch (e) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red(`\n[${command.name}] failed:\n`)); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (e instanceof _utils_errors__WEBPACK_IMPORTED_MODULE_4__["CliError"]) { + const msg = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.red(`CliError: ${e.message}\n`); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default()(msg, 80)); + const keys = Object.keys(e.meta); -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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. - */ + if (keys.length > 0) { + const metaOutput = keys.map(key => { + const value = e.meta[key]; + return `${key}: ${value}`; + }); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write('Additional debugging info:\n'); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(indent_string__WEBPACK_IMPORTED_MODULE_1___default()(metaOutput.join('\n'), 3)); + } + } else { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(e.stack); + } + process.exit(1); + } +} function toArray(value) { - if (value == null) { - return []; - } - return Array.isArray(value) ? value : [value]; + if (value == null) { + return []; + } + + return Array.isArray(value) ? value : [value]; } /***/ }), @@ -31602,26 +31483,15 @@ module.exports = () => { /***/ }), /* 366 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.renderProjectsTree = renderProjectsTree; - -var _chalk = __webpack_require__(2); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _path = __webpack_require__(16); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderProjectsTree", function() { return renderProjectsTree; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -31640,173 +31510,228 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de * specific language governing permissions and limitations * under the License. */ + + const projectKey = Symbol('__project'); function renderProjectsTree(rootPath, projects) { - const projectsTree = buildProjectsTree(rootPath, projects); - return treeToString(createTreeStructure(projectsTree)); + const projectsTree = buildProjectsTree(rootPath, projects); + return treeToString(createTreeStructure(projectsTree)); } + function treeToString(tree) { - return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n'); + return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n'); } + function childrenToStrings(tree, treePrefix) { - if (tree === undefined) { - return []; - } - let strings = []; - tree.forEach((node, index) => { - const isLastNode = tree.length - 1 === index; - const nodePrefix = isLastNode ? '└── ' : '├── '; - const childPrefix = isLastNode ? ' ' : '│ '; - const childrenPrefix = treePrefix + childPrefix; - strings.push(`${treePrefix}${nodePrefix}${node.name}`); - strings = strings.concat(childrenToStrings(node.children, childrenPrefix)); - }); - return strings; + if (tree === undefined) { + return []; + } + + let strings = []; + tree.forEach((node, index) => { + const isLastNode = tree.length - 1 === index; + const nodePrefix = isLastNode ? '└── ' : '├── '; + const childPrefix = isLastNode ? ' ' : '│ '; + const childrenPrefix = treePrefix + childPrefix; + strings.push(`${treePrefix}${nodePrefix}${node.name}`); + strings = strings.concat(childrenToStrings(node.children, childrenPrefix)); + }); + return strings; } + function createTreeStructure(tree) { - let name; - const children = []; - for (const [dir, project] of tree.entries()) { - // This is a leaf node (aka a project) - if (typeof project === 'string') { - name = _chalk2.default.green(project); - continue; - } - // If there's only one project and the key indicates it's a leaf node, we - // know that we're at a package folder that contains a package.json, so we - // "inline it" so we don't get unnecessary levels, i.e. we'll just see - // `foo` instead of `foo -> foo`. - if (project.size === 1 && project.has(projectKey)) { - const projectName = project.get(projectKey); - children.push({ - children: [], - name: dirOrProjectName(dir, projectName) - }); - continue; - } - const subtree = createTreeStructure(project); - // If the name is specified, we know there's a package at the "root" of the - // subtree itself. - if (subtree.name !== undefined) { - const projectName = subtree.name; - children.push({ - children: subtree.children, - name: dirOrProjectName(dir, projectName) - }); - continue; - } - // Special-case whenever we have one child, so we don't get unnecessary - // folders in the output. E.g. instead of `foo -> bar -> baz` we get - // `foo/bar/baz` instead. - if (subtree.children && subtree.children.length === 1) { - const child = subtree.children[0]; - const newName = _chalk2.default.dim(_path2.default.join(dir.toString(), child.name)); - children.push({ - children: child.children, - name: newName - }); - continue; - } - children.push({ - children: subtree.children, - name: _chalk2.default.dim(dir.toString()) - }); + let name; + const children = []; + + for (const [dir, project] of tree.entries()) { + // This is a leaf node (aka a project) + if (typeof project === 'string') { + name = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(project); + continue; + } // If there's only one project and the key indicates it's a leaf node, we + // know that we're at a package folder that contains a package.json, so we + // "inline it" so we don't get unnecessary levels, i.e. we'll just see + // `foo` instead of `foo -> foo`. + + + if (project.size === 1 && project.has(projectKey)) { + const projectName = project.get(projectKey); + children.push({ + children: [], + name: dirOrProjectName(dir, projectName) + }); + continue; } - return { name, children }; + + const subtree = createTreeStructure(project); // If the name is specified, we know there's a package at the "root" of the + // subtree itself. + + if (subtree.name !== undefined) { + const projectName = subtree.name; + children.push({ + children: subtree.children, + name: dirOrProjectName(dir, projectName) + }); + continue; + } // Special-case whenever we have one child, so we don't get unnecessary + // folders in the output. E.g. instead of `foo -> bar -> baz` we get + // `foo/bar/baz` instead. + + + if (subtree.children && subtree.children.length === 1) { + const child = subtree.children[0]; + const newName = chalk__WEBPACK_IMPORTED_MODULE_0___default.a.dim(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(dir.toString(), child.name)); + children.push({ + children: child.children, + name: newName + }); + continue; + } + + children.push({ + children: subtree.children, + name: chalk__WEBPACK_IMPORTED_MODULE_0___default.a.dim(dir.toString()) + }); + } + + return { + name, + children + }; } + function dirOrProjectName(dir, projectName) { - return dir === projectName ? _chalk2.default.green(dir) : _chalk2.default`{dim ${dir.toString()} ({reset.green ${projectName}})}`; + return dir === projectName ? chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green(dir) : chalk__WEBPACK_IMPORTED_MODULE_0___default.a`{dim ${dir.toString()} ({reset.green ${projectName}})}`; } + function buildProjectsTree(rootPath, projects) { - const tree = new Map(); - for (const project of projects.values()) { - if (rootPath === project.path) { - tree.set(projectKey, project.name); - } else { - const relativeProjectPath = _path2.default.relative(rootPath, project.path); - addProjectToTree(tree, relativeProjectPath.split(_path2.default.sep), project); - } + const tree = new Map(); + + for (const project of projects.values()) { + if (rootPath === project.path) { + tree.set(projectKey, project.name); + } else { + const relativeProjectPath = path__WEBPACK_IMPORTED_MODULE_1___default.a.relative(rootPath, project.path); + addProjectToTree(tree, relativeProjectPath.split(path__WEBPACK_IMPORTED_MODULE_1___default.a.sep), project); } - return tree; + } + + return tree; } + function addProjectToTree(tree, pathParts, project) { - if (pathParts.length === 0) { - tree.set(projectKey, project.name); - } else { - const [currentDir, ...rest] = pathParts; - if (!tree.has(currentDir)) { - tree.set(currentDir, new Map()); - } - const subtree = tree.get(currentDir); - addProjectToTree(subtree, rest, project); + if (pathParts.length === 0) { + tree.set(projectKey, project.name); + } else { + const [currentDir, ...rest] = pathParts; + + if (!tree.has(currentDir)) { + tree.set(currentDir, new Map()); } + + const subtree = tree.get(currentDir); + addProjectToTree(subtree, rest, project); + } } /***/ }), /* 367 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(368); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(547); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _build_production_projects = __webpack_require__(368); - -Object.defineProperty(exports, 'buildProductionProjects', { - enumerable: true, - get: function () { - return _build_production_projects.buildProductionProjects; - } -}); +/* + * 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. + */ -var _prepare_project_dependencies = __webpack_require__(547); -Object.defineProperty(exports, 'prepareExternalProjectDependencies', { - enumerable: true, - get: function () { - return _prepare_project_dependencies.prepareExternalProjectDependencies; - } -}); /***/ }), /* 368 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(369); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(132); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(54); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.buildProductionProjects = undefined; - -let buildProductionProjects = exports.buildProductionProjects = (() => { - var _ref = _asyncToGenerator(function* ({ kibanaRoot, buildRoots }) { - const projects = yield getProductionProjects(kibanaRoot); - const projectGraph = (0, _projects.buildProjectGraph)(projects); - const batchedProjects = (0, _projects.topologicallyBatchProjects)(projects, projectGraph); - const projectNames = [...projects.values()].map(function (project) { - return project.name; - }); - _log.log.write(`Preparing production build for [${projectNames.join(', ')}]`); - for (const batch of batchedProjects) { - for (const project of batch) { - yield deleteTarget(project); - yield buildProject(project); - for (const buildRoot of buildRoots) { - yield copyToBuild(project, kibanaRoot, buildRoot); - } - } - } - }); - return function buildProductionProjects(_x) { - return _ref.apply(this, arguments); - }; -})(); + + + + + +async function buildProductionProjects({ + kibanaRoot, + buildRoots +}) { + const projects = await getProductionProjects(kibanaRoot); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); + const projectNames = [...projects.values()].map(project => project.name); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(`Preparing production build for [${projectNames.join(', ')}]`); + + for (const batch of batchedProjects) { + for (const project of batch) { + await deleteTarget(project); + await buildProject(project); + + for (const buildRoot of buildRoots) { + await copyToBuild(project, kibanaRoot, buildRoot); + } + } + } +} /** * Returns the subset of projects that should be built into the production * bundle. As we copy these into Kibana's `node_modules` during the build step, @@ -31814,48 +31739,32 @@ let buildProductionProjects = exports.buildProductionProjects = (() => { * we only include Kibana's transitive _production_ dependencies. */ +async function getProductionProjects(rootPath) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(rootPath, {}); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); + const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])([projects.get('kibana')], projects, { + onlyProductionDependencies: true + }); // We remove Kibana, as we're already building Kibana -let getProductionProjects = (() => { - var _ref2 = _asyncToGenerator(function* (rootPath) { - const projectPaths = (0, _config.getProjectPaths)(rootPath, {}); - const projects = yield (0, _projects.getProjects)(rootPath, projectPaths); - const productionProjects = (0, _projects.includeTransitiveProjects)([projects.get('kibana')], projects, { - onlyProductionDependencies: true - }); - // We remove Kibana, as we're already building Kibana - productionProjects.delete('kibana'); - return productionProjects; - }); - - return function getProductionProjects(_x2) { - return _ref2.apply(this, arguments); - }; -})(); - -let deleteTarget = (() => { - var _ref3 = _asyncToGenerator(function* (project) { - const targetDir = project.targetLocation; - if (yield (0, _fs.isDirectory)(targetDir)) { - yield (0, _del2.default)(targetDir, { force: true }); - } - }); + productionProjects.delete('kibana'); + return productionProjects; +} - return function deleteTarget(_x3) { - return _ref3.apply(this, arguments); - }; -})(); +async function deleteTarget(project) { + const targetDir = project.targetLocation; -let buildProject = (() => { - var _ref4 = _asyncToGenerator(function* (project) { - if (project.hasScript('build')) { - yield project.runScript('build'); - } + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { + await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { + force: true }); + } +} - return function buildProject(_x4) { - return _ref4.apply(this, arguments); - }; -})(); +async function buildProject(project) { + if (project.hasScript('build')) { + await project.runScript('build'); + } +} /** * Copy all the project's files from its "intermediate build directory" and * into the build. The intermediate directory can either be the root of the @@ -31869,73 +31778,26 @@ let buildProject = (() => { */ -let copyToBuild = (() => { - var _ref5 = _asyncToGenerator(function* (project, kibanaRoot, buildRoot) { - // We want the package to have the same relative location within the build - const relativeProjectPath = (0, _path.relative)(kibanaRoot, project.path); - const buildProjectPath = (0, _path.resolve)(buildRoot, relativeProjectPath); - yield (0, _cpy2.default)(['**/*', '!node_modules/**'], buildProjectPath, { - cwd: project.getIntermediateBuildDirectory(), - dot: true, - nodir: true, - parents: true - }); - // If a project is using an intermediate build directory, we special-case our - // handling of `package.json`, as the project build process might have copied - // (a potentially modified) `package.json` into the intermediate build - // directory already. If so, we want to use that `package.json` as the basis - // for creating the production-ready `package.json`. If it's not present in - // the intermediate build, we fall back to using the project's already defined - // `package.json`. - const packageJson = (yield (0, _fs.isFile)((0, _path.join)(buildProjectPath, 'package.json'))) ? yield (0, _package_json.readPackageJson)(buildProjectPath) : project.json; - yield (0, _package_json.writePackageJson)(buildProjectPath, packageJson); - }); - - return function copyToBuild(_x5, _x6, _x7) { - return _ref5.apply(this, arguments); - }; -})(); - -var _cpy = __webpack_require__(369); - -var _cpy2 = _interopRequireDefault(_cpy); - -var _del = __webpack_require__(134); - -var _del2 = _interopRequireDefault(_del); - -var _path = __webpack_require__(16); - -var _config = __webpack_require__(132); - -var _fs = __webpack_require__(20); +async function copyToBuild(project, kibanaRoot, buildRoot) { + // We want the package to have the same relative location within the build + const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); + const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); + await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { + cwd: project.getIntermediateBuildDirectory(), + dot: true, + nodir: true, + parents: true + }); // If a project is using an intermediate build directory, we special-case our + // handling of `package.json`, as the project build process might have copied + // (a potentially modified) `package.json` into the intermediate build + // directory already. If so, we want to use that `package.json` as the basis + // for creating the production-ready `package.json`. If it's not present in + // the intermediate build, we fall back to using the project's already defined + // `package.json`. -var _log = __webpack_require__(33); - -var _package_json = __webpack_require__(54); - -var _projects = __webpack_require__(35); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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 packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; + await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); +} /***/ }), /* 369 */ @@ -55219,75 +55081,67 @@ module.exports = CpyError; /***/ }), /* 547 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return prepareExternalProjectDependencies; }); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53); +/* + * 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. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.prepareExternalProjectDependencies = undefined; +/** + * All external projects are located within `./plugins/{plugin}` relative + * to the Kibana root directory or `../kibana-extra/{plugin}` relative + * to Kibana itself. + */ +const isKibanaDep = depVersion => depVersion.includes('../../kibana/'); /** * This prepares the dependencies for an _external_ project. */ -let prepareExternalProjectDependencies = exports.prepareExternalProjectDependencies = (() => { - var _ref = _asyncToGenerator(function* (projectPath) { - const project = yield _project.Project.fromPath(projectPath); - if (!project.hasDependencies()) { - return; - } - const deps = project.allDependencies; - for (const depName of Object.keys(deps)) { - const depVersion = deps[depName]; - // Kibana currently only supports `link:` dependencies on Kibana's own - // packages, as these are packaged into the `node_modules` folder when - // Kibana is built, so we don't need to take any action to enable - // `require(...)` to resolve for these packages. - if ((0, _package_json.isLinkDependency)(depVersion) && !isKibanaDep(depVersion)) { - // For non-Kibana packages we need to set up symlinks during the - // installation process, but this is not something we support yet. - throw new Error('This plugin is using `link:` dependencies for non-Kibana packages'); - } - } - }); - return function prepareExternalProjectDependencies(_x) { - return _ref.apply(this, arguments); - }; -})(); -var _package_json = __webpack_require__(54); +async function prepareExternalProjectDependencies(projectPath) { + const project = await _utils_project__WEBPACK_IMPORTED_MODULE_1__["Project"].fromPath(projectPath); -var _project = __webpack_require__(53); + if (!project.hasDependencies()) { + return; + } -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* - * 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 deps = project.allDependencies; + for (const depName of Object.keys(deps)) { + const depVersion = deps[depName]; // Kibana currently only supports `link:` dependencies on Kibana's own + // packages, as these are packaged into the `node_modules` folder when + // Kibana is built, so we don't need to take any action to enable + // `require(...)` to resolve for these packages. -/** - * All external projects are located within `./plugins/{plugin}` relative - * to the Kibana root directory or `../kibana-extra/{plugin}` relative - * to Kibana itself. - */ -const isKibanaDep = depVersion => depVersion.includes('../../kibana/'); + if (Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_0__["isLinkDependency"])(depVersion) && !isKibanaDep(depVersion)) { + // For non-Kibana packages we need to set up symlinks during the + // installation process, but this is not something we support yet. + throw new Error('This plugin is using `link:` dependencies for non-Kibana packages'); + } + } +} /***/ }) /******/ ]); \ No newline at end of file diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 6248e919976db2..86d67c0bcfe1f7 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,6 +10,11 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { + "@babel/core": "^7.3.4", + "@babel/plugin-proposal-class-properties": "^7.3.4", + "@babel/plugin-proposal-object-rest-spread": "^7.3.4", + "@babel/preset-env": "^7.3.4", + "@babel/preset-typescript": "^7.3.3", "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", @@ -32,10 +37,7 @@ "@types/tempy": "^0.1.0", "@types/wrap-ansi": "^2.0.14", "@types/write-pkg": "^3.1.0", - "babel-core": "^6.26.3", - "babel-loader": "^7.1.5", - "babel-preset-env": "^1.7.0", - "babel-preset-stage-3": "^6.24.1", + "babel-loader": "^8.0.5", "chalk": "^2.4.1", "cmd-shim": "^2.0.2", "cpy": "^7.0.1", @@ -60,7 +62,6 @@ "strip-ansi": "^4.0.0", "strong-log-transformer": "^2.1.0", "tempy": "^0.2.1", - "ts-loader": "^5.2.2", "typescript": "^3.3.3333", "unlazy-loader": "^0.1.3", "webpack": "^4.23.1", diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json index df6ad1d3d6d9b9..c1269fc7c037b4 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/package.json @@ -4,10 +4,11 @@ "private": true, "main": "./target/index.js", "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1" + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4" }, "scripts": { - "build": "babel --presets env --out-dir target src" + "build": "babel --presets=@babel/preset-env --out-dir target src" } } diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json index 385aa59bffc7a0..8b8225594c5aca 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/package.json @@ -7,11 +7,12 @@ "@elastic/bar": "link:../bar" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/core": "^7.3.4", + "@babel/cli": "^7.2.3", + "@babel/preset-env": "^7.3.4", "moment": "2.20.1" }, "scripts": { - "build": "babel --presets env --out-dir target src" + "build": "babel --presets=@babel/preset-env --out-dir target src" } } diff --git a/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap b/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap index 94642340e0d9d6..5049c692aae68a 100644 --- a/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap +++ b/packages/kbn-pm/src/production/integration_tests/__snapshots__/build_production_projects.test.ts.snap @@ -20,14 +20,15 @@ Array [ exports[`kbn-pm production builds and copies projects for production: packages/bar/package.json 1`] = ` Object { "devDependencies": Object { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4", }, "main": "./target/index.js", "name": "@elastic/bar", "private": true, "scripts": Object { - "build": "babel --presets env --out-dir target src", + "build": "babel --presets=@babel/preset-env --out-dir target src", }, "version": "1.0.0", } @@ -47,15 +48,16 @@ Object { "@elastic/bar": "link:../bar", }, "devDependencies": Object { - "babel-cli": "^6.26.0", - "babel-preset-env": "^1.6.1", + "@babel/cli": "^7.2.3", + "@babel/core": "^7.3.4", + "@babel/preset-env": "^7.3.4", "moment": "2.20.1", }, "main": "./target/index.js", "name": "@elastic/foo", "private": true, "scripts": Object { - "build": "babel --presets env --out-dir target src", + "build": "babel --presets=@babel/preset-env --out-dir target src", }, "version": "1.0.0", } diff --git a/packages/kbn-pm/tsconfig.json b/packages/kbn-pm/tsconfig.json index f7c8cdab167821..2141c5502ae98a 100644 --- a/packages/kbn-pm/tsconfig.json +++ b/packages/kbn-pm/tsconfig.json @@ -4,7 +4,7 @@ "dist" ], "include": [ - "./src/**/*.ts" + "./src/**/*.ts", ], "compilerOptions": { "types": [ diff --git a/packages/kbn-pm/webpack.config.js b/packages/kbn-pm/webpack.config.js index 1424850265e072..ff77d3cfb7e9ce 100644 --- a/packages/kbn-pm/webpack.config.js +++ b/packages/kbn-pm/webpack.config.js @@ -44,15 +44,6 @@ module.exports = { { loader: 'babel-loader', }, - { - loader: 'ts-loader', - options: { - compilerOptions: { - // enable esnext modules so webpack can do its thing better - module: 'esnext', - }, - }, - }, ], exclude: /node_modules/, }, diff --git a/packages/kbn-test/babel.config.js b/packages/kbn-test/babel.config.js index 962d7d3e05c55c..ff657603f4c8d2 100644 --- a/packages/kbn-test/babel.config.js +++ b/packages/kbn-test/babel.config.js @@ -18,6 +18,6 @@ */ module.exports = { - presets: ['@kbn/babel-preset/node_preset_7'], + presets: ['@kbn/babel-preset/node_preset'], ignore: ['**/*.test.js'], }; diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index aa57d854e14cc7..56790e8cb194e6 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -10,9 +10,9 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { + "@babel/cli": "^7.2.3", "@kbn/babel-preset": "1.0.0", - "@kbn/dev-utils": "1.0.0", - "@babel/cli": "^7.2.3" + "@kbn/dev-utils": "1.0.0" }, "dependencies": { "chalk": "^2.4.1", diff --git a/packages/kbn-ui-framework/doc_site/src/index.js b/packages/kbn-ui-framework/doc_site/src/index.js index 094437d85e6b64..f53e8a608e1a11 100644 --- a/packages/kbn-ui-framework/doc_site/src/index.js +++ b/packages/kbn-ui-framework/doc_site/src/index.js @@ -19,7 +19,7 @@ require('./main.scss'); -import 'babel-polyfill'; +import '@babel/polyfill'; import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 87e586e90ec2f5..f2b9c2f7e71390 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -26,16 +26,16 @@ "uuid": "3.0.1" }, "peerDependencies": { - "enzyme": "3.2.0", - "enzyme-adapter-react-16": "^1.1.1" + "enzyme": "^3.8.0", + "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", "@elastic/eui": "0.0.23", "@kbn/babel-preset": "1.0.0", "autoprefixer": "6.5.4", - "babel-core": "^6.26.3", - "babel-loader": "^7.1.5", - "babel-polyfill": "^6.26.0", + "babel-loader": "^8.0.5", "brace": "0.10.0", "chalk": "^2.4.1", "chokidar": "1.6.0", @@ -43,7 +43,7 @@ "expose-loader": "^0.7.5", "file-loader": "^2.0.0", "grunt": "1.0.3", - "grunt-babel": "^7.0.0", + "grunt-babel": "^8.0.0", "grunt-contrib-clean": "^1.1.0", "grunt-contrib-copy": "^1.0.0", "highlight.js": "9.0.0", diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts new file mode 100644 index 00000000000000..cb3f45361d5f7f --- /dev/null +++ b/src/core/public/core_system.test.mocks.ts @@ -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. + */ + +import { basePathServiceMock } from './base_path/base_path_service.mock'; +import { chromeServiceMock } from './chrome/chrome_service.mock'; +import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; +import { httpServiceMock } from './http/http_service.mock'; +import { i18nServiceMock } from './i18n/i18n_service.mock'; +import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; +import { legacyPlatformServiceMock } from './legacy/legacy_service.mock'; +import { notificationServiceMock } from './notifications/notifications_service.mock'; +import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; + +export const MockLegacyPlatformService = legacyPlatformServiceMock.create(); +export const LegacyPlatformServiceConstructor = jest + .fn() + .mockImplementation(() => MockLegacyPlatformService); +jest.doMock('./legacy', () => ({ + LegacyPlatformService: LegacyPlatformServiceConstructor, +})); + +export const MockInjectedMetadataService = injectedMetadataServiceMock.create(); +export const InjectedMetadataServiceConstructor = jest + .fn() + .mockImplementation(() => MockInjectedMetadataService); +jest.doMock('./injected_metadata', () => ({ + InjectedMetadataService: InjectedMetadataServiceConstructor, +})); + +export const MockFatalErrorsService = fatalErrorsServiceMock.create(); +export const FatalErrorsServiceConstructor = jest + .fn() + .mockImplementation(() => MockFatalErrorsService); +jest.doMock('./fatal_errors', () => ({ + FatalErrorsService: FatalErrorsServiceConstructor, +})); + +export const MockI18nService = i18nServiceMock.create(); +export const I18nServiceConstructor = jest.fn().mockImplementation(() => MockI18nService); +jest.doMock('./i18n', () => ({ + I18nService: I18nServiceConstructor, +})); + +export const MockNotificationsService = notificationServiceMock.create(); +export const NotificationServiceConstructor = jest + .fn() + .mockImplementation(() => MockNotificationsService); +jest.doMock('./notifications', () => ({ + NotificationsService: NotificationServiceConstructor, +})); + +export const MockHttpService = httpServiceMock.create(); +export const HttpServiceConstructor = jest.fn().mockImplementation(() => MockHttpService); +jest.doMock('./http', () => ({ + HttpService: HttpServiceConstructor, +})); + +export const MockBasePathService = basePathServiceMock.create(); +export const BasePathServiceConstructor = jest.fn().mockImplementation(() => MockBasePathService); +jest.doMock('./base_path', () => ({ + BasePathService: BasePathServiceConstructor, +})); + +export const MockUiSettingsService = uiSettingsServiceMock.create(); +export const UiSettingsServiceConstructor = jest + .fn() + .mockImplementation(() => MockUiSettingsService); +jest.doMock('./ui_settings', () => ({ + UiSettingsService: UiSettingsServiceConstructor, +})); + +export const MockChromeService = chromeServiceMock.create(); +export const ChromeServiceConstructor = jest.fn().mockImplementation(() => MockChromeService); +jest.doMock('./chrome', () => ({ + ChromeService: ChromeServiceConstructor, +})); diff --git a/src/core/public/core_system.test.ts b/src/core/public/core_system.test.ts index 9d9620e3b0853e..3a8580127f15cf 100644 --- a/src/core/public/core_system.test.ts +++ b/src/core/public/core_system.test.ts @@ -17,73 +17,26 @@ * under the License. */ -import { basePathServiceMock } from './base_path/base_path_service.mock'; -import { chromeServiceMock } from './chrome/chrome_service.mock'; -import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; -import { httpServiceMock } from './http/http_service.mock'; -import { i18nServiceMock } from './i18n/i18n_service.mock'; -import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; -import { legacyPlatformServiceMock } from './legacy/legacy_service.mock'; -import { notificationServiceMock } from './notifications/notifications_service.mock'; -import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; - -const MockLegacyPlatformService = legacyPlatformServiceMock.create(); -const LegacyPlatformServiceConstructor = jest - .fn() - .mockImplementation(() => MockLegacyPlatformService); -jest.mock('./legacy', () => ({ - LegacyPlatformService: LegacyPlatformServiceConstructor, -})); - -const MockInjectedMetadataService = injectedMetadataServiceMock.create(); -const InjectedMetadataServiceConstructor = jest - .fn() - .mockImplementation(() => MockInjectedMetadataService); -jest.mock('./injected_metadata', () => ({ - InjectedMetadataService: InjectedMetadataServiceConstructor, -})); - -const MockFatalErrorsService = fatalErrorsServiceMock.create(); -const FatalErrorsServiceConstructor = jest.fn().mockImplementation(() => MockFatalErrorsService); -jest.mock('./fatal_errors', () => ({ - FatalErrorsService: FatalErrorsServiceConstructor, -})); - -const MockI18nService = i18nServiceMock.create(); -const I18nServiceConstructor = jest.fn().mockImplementation(() => MockI18nService); -jest.mock('./i18n', () => ({ - I18nService: I18nServiceConstructor, -})); - -const MockNotificationsService = notificationServiceMock.create(); -const NotificationServiceConstructor = jest.fn().mockImplementation(() => MockNotificationsService); -jest.mock('./notifications', () => ({ - NotificationsService: NotificationServiceConstructor, -})); - -const MockHttpService = httpServiceMock.create(); -const HttpServiceConstructor = jest.fn().mockImplementation(() => MockHttpService); -jest.mock('./http', () => ({ - HttpService: HttpServiceConstructor, -})); - -const MockBasePathService = basePathServiceMock.create(); -const BasePathServiceConstructor = jest.fn().mockImplementation(() => MockBasePathService); -jest.mock('./base_path', () => ({ - BasePathService: BasePathServiceConstructor, -})); - -const MockUiSettingsService = uiSettingsServiceMock.create(); -const UiSettingsServiceConstructor = jest.fn().mockImplementation(() => MockUiSettingsService); -jest.mock('./ui_settings', () => ({ - UiSettingsService: UiSettingsServiceConstructor, -})); - -const MockChromeService = chromeServiceMock.create(); -const ChromeServiceConstructor = jest.fn().mockImplementation(() => MockChromeService); -jest.mock('./chrome', () => ({ - ChromeService: ChromeServiceConstructor, -})); +import { + BasePathServiceConstructor, + ChromeServiceConstructor, + FatalErrorsServiceConstructor, + HttpServiceConstructor, + I18nServiceConstructor, + InjectedMetadataServiceConstructor, + LegacyPlatformServiceConstructor, + MockBasePathService, + MockChromeService, + MockFatalErrorsService, + MockHttpService, + MockI18nService, + MockInjectedMetadataService, + MockLegacyPlatformService, + MockNotificationsService, + MockUiSettingsService, + NotificationServiceConstructor, + UiSettingsServiceConstructor, +} from './core_system.test.mocks'; import { CoreSystem } from './core_system'; jest.spyOn(CoreSystem.prototype, 'stop'); diff --git a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap index a58d0f6fc9c37f..c6912764db2af5 100644 --- a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap +++ b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap @@ -53,8 +53,7 @@ exports[`rendering render matches snapshot 1`] = ` body={

diff --git a/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts b/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts new file mode 100644 index 00000000000000..b998817a1bfcc3 --- /dev/null +++ b/src/core/public/fatal_errors/fatal_errors_service.test.mocks.ts @@ -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 mockRender = jest.fn(); +jest.mock('react-dom', () => { + return { + render: mockRender, + }; +}); diff --git a/src/core/public/fatal_errors/fatal_errors_service.test.ts b/src/core/public/fatal_errors/fatal_errors_service.test.ts index 6f3842fc4e0e92..b1ad92c8c2f622 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.test.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.test.ts @@ -24,12 +24,7 @@ expect.addSnapshotSerializer({ print: () => `Rx.Observable`, }); -const mockRender = jest.fn(); -jest.mock('react-dom', () => { - return { - render: mockRender, - }; -}); +import { mockRender } from './fatal_errors_service.test.mocks'; import { FatalErrorsService } from './fatal_errors_service'; diff --git a/src/core/public/notifications/toasts/toasts_service.test.mocks.ts b/src/core/public/notifications/toasts/toasts_service.test.mocks.ts new file mode 100644 index 00000000000000..90ea76c5515645 --- /dev/null +++ b/src/core/public/notifications/toasts/toasts_service.test.mocks.ts @@ -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 mockReactDomRender = jest.fn(); +export const mockReactDomUnmount = jest.fn(); +jest.mock('react-dom', () => ({ + render: mockReactDomRender, + unmountComponentAtNode: mockReactDomUnmount, +})); diff --git a/src/core/public/notifications/toasts/toasts_service.test.tsx b/src/core/public/notifications/toasts/toasts_service.test.tsx index d380ad5b77ea6c..849fdda97f9392 100644 --- a/src/core/public/notifications/toasts/toasts_service.test.tsx +++ b/src/core/public/notifications/toasts/toasts_service.test.tsx @@ -17,12 +17,7 @@ * under the License. */ -const mockReactDomRender = jest.fn(); -const mockReactDomUnmount = jest.fn(); -jest.mock('react-dom', () => ({ - render: mockReactDomRender, - unmountComponentAtNode: mockReactDomUnmount, -})); +import { mockReactDomRender, mockReactDomUnmount } from './toasts_service.test.mocks'; import { ToastsService } from './toasts_service'; import { ToastsSetup } from './toasts_start'; diff --git a/src/core/public/ui_settings/ui_settings_service.test.mocks.ts b/src/core/public/ui_settings/ui_settings_service.test.mocks.ts new file mode 100644 index 00000000000000..458a9efdea4694 --- /dev/null +++ b/src/core/public/ui_settings/ui_settings_service.test.mocks.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +function mockClass( + module: string, + Class: { new (...args: any[]): T }, + setup: (instance: any, args: any[]) => void +) { + const MockClass = jest.fn(function(this: any, ...args: any[]) { + setup(this, args); + }); + + // define the mock name which is used in some snapshots + MockClass.mockName(`Mock${Class.name}`); + + // define the class name for the MockClass which is used in other snapshots + Object.defineProperty(MockClass, 'name', { + value: `Mock${Class.name}`, + }); + + jest.doMock(module, () => ({ + [Class.name]: MockClass, + })); + + return MockClass; +} + +// Mock the UiSettingsApi class +import { UiSettingsApi } from './ui_settings_api'; +export const MockUiSettingsApi = mockClass('./ui_settings_api', UiSettingsApi, inst => { + inst.stop = jest.fn(); + inst.getLoadingCount$ = jest.fn().mockReturnValue({ + loadingCountObservable: true, + }); +}); + +// Mock the UiSettingsClient class +import { UiSettingsClient } from './ui_settings_client'; +export const MockUiSettingsClient = mockClass('./ui_settings_client', UiSettingsClient, inst => { + inst.stop = jest.fn(); +}); diff --git a/src/core/public/ui_settings/ui_settings_service.test.ts b/src/core/public/ui_settings/ui_settings_service.test.ts index e58b517984fc5d..f1bfab2981d6e4 100644 --- a/src/core/public/ui_settings/ui_settings_service.test.ts +++ b/src/core/public/ui_settings/ui_settings_service.test.ts @@ -17,44 +17,7 @@ * under the License. */ -function mockClass( - module: string, - Class: { new (...args: any[]): T }, - setup: (instance: any, args: any[]) => void -) { - const MockClass = jest.fn(function(this: any, ...args: any[]) { - setup(this, args); - }); - - // define the mock name which is used in some snapshots - MockClass.mockName(`Mock${Class.name}`); - - // define the class name for the MockClass which is used in other snapshots - Object.defineProperty(MockClass, 'name', { - value: `Mock${Class.name}`, - }); - - jest.mock(module, () => ({ - [Class.name]: MockClass, - })); - - return MockClass; -} - -// Mock the UiSettingsApi class -import { UiSettingsApi } from './ui_settings_api'; -const MockUiSettingsApi = mockClass('./ui_settings_api', UiSettingsApi, inst => { - inst.stop = jest.fn(); - inst.getLoadingCount$ = jest.fn().mockReturnValue({ - loadingCountObservable: true, - }); -}); - -// Mock the UiSettingsClient class -import { UiSettingsClient } from './ui_settings_client'; -const MockUiSettingsClient = mockClass('./ui_settings_client', UiSettingsClient, inst => { - inst.stop = jest.fn(); -}); +import { MockUiSettingsApi, MockUiSettingsClient } from './ui_settings_service.test.mocks'; import { basePathServiceMock } from '../base_path/base_path_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; diff --git a/src/core/server/config/config_service.mock.ts b/src/core/server/config/config_service.mock.ts index d9f460905fc43a..92b0f117b1a02d 100644 --- a/src/core/server/config/config_service.mock.ts +++ b/src/core/server/config/config_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { BehaviorSubject } from 'rxjs'; import { ObjectToConfigAdapter } from './object_to_config_adapter'; diff --git a/src/core/server/config/config_service.test.mocks.ts b/src/core/server/config/config_service.test.mocks.ts new file mode 100644 index 00000000000000..8fa1ec997d6258 --- /dev/null +++ b/src/core/server/config/config_service.test.mocks.ts @@ -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 mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../package.json', () => mockPackage); diff --git a/src/core/server/config/config_service.test.ts b/src/core/server/config/config_service.test.ts index 7a10d4992e2c2a..a054786c80f7d0 100644 --- a/src/core/server/config/config_service.test.ts +++ b/src/core/server/config/config_service.test.ts @@ -22,8 +22,7 @@ import { BehaviorSubject } from 'rxjs'; import { first } from 'rxjs/operators'; -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +import { mockPackage } from './config_service.test.mocks'; import { schema, Type, TypeOf } from '@kbn/config-schema'; diff --git a/src/core/server/config/env.test.mocks.ts b/src/core/server/config/env.test.mocks.ts new file mode 100644 index 00000000000000..be65aa17270765 --- /dev/null +++ b/src/core/server/config/env.test.mocks.ts @@ -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. + */ + +jest.mock('process', () => ({ + cwd() { + return '/test/cwd'; + }, +})); + +jest.mock('path', () => ({ + resolve(...pathSegments: string[]) { + return pathSegments.join('/'); + }, +})); + +export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../package.json', () => mockPackage); diff --git a/src/core/server/config/env.test.ts b/src/core/server/config/env.test.ts index 3c251b7339e49e..13bd05c3b1c842 100644 --- a/src/core/server/config/env.test.ts +++ b/src/core/server/config/env.test.ts @@ -17,20 +17,7 @@ * under the License. */ -jest.mock('process', () => ({ - cwd() { - return '/test/cwd'; - }, -})); - -jest.mock('path', () => ({ - resolve(...pathSegments: string[]) { - return pathSegments.join('/'); - }, -})); - -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +import { mockPackage } from './env.test.mocks'; import { Env } from '.'; import { getEnvOptions } from './__mocks__/env'; diff --git a/src/core/server/config/raw_config_service.test.mocks.ts b/src/core/server/config/raw_config_service.test.mocks.ts new file mode 100644 index 00000000000000..be43b0f64e6583 --- /dev/null +++ b/src/core/server/config/raw_config_service.test.mocks.ts @@ -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 const mockGetConfigFromFiles = jest.fn(); + +jest.mock('./read_config', () => ({ + getConfigFromFiles: mockGetConfigFromFiles, +})); diff --git a/src/core/server/config/raw_config_service.test.ts b/src/core/server/config/raw_config_service.test.ts index 0cd0dc45cd9392..361cef0d042ea9 100644 --- a/src/core/server/config/raw_config_service.test.ts +++ b/src/core/server/config/raw_config_service.test.ts @@ -17,11 +17,7 @@ * under the License. */ -const mockGetConfigFromFiles = jest.fn(); - -jest.mock('./read_config', () => ({ - getConfigFromFiles: mockGetConfigFromFiles, -})); +import { mockGetConfigFromFiles } from './raw_config_service.test.mocks'; import { first } from 'rxjs/operators'; import { RawConfigService } from '.'; diff --git a/src/core/server/elasticsearch/cluster_client.test.mocks.ts b/src/core/server/elasticsearch/cluster_client.test.mocks.ts new file mode 100644 index 00000000000000..4a8553d1d5f991 --- /dev/null +++ b/src/core/server/elasticsearch/cluster_client.test.mocks.ts @@ -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 MockClient = jest.fn(); +jest.mock('elasticsearch', () => ({ + // Jest types don't include `requireActual` right now. + ...jest.requireActual('elasticsearch'), + Client: MockClient, +})); + +export const MockScopedClusterClient = jest.fn(); +jest.mock('./scoped_cluster_client', () => ({ + ScopedClusterClient: MockScopedClusterClient, +})); + +export const mockParseElasticsearchClientConfig = jest.fn(); +jest.mock('./elasticsearch_client_config', () => ({ + parseElasticsearchClientConfig: mockParseElasticsearchClientConfig, +})); diff --git a/src/core/server/elasticsearch/cluster_client.test.ts b/src/core/server/elasticsearch/cluster_client.test.ts index da511c282981ef..30a1ac7a038ede 100644 --- a/src/core/server/elasticsearch/cluster_client.test.ts +++ b/src/core/server/elasticsearch/cluster_client.test.ts @@ -19,22 +19,11 @@ import { ElasticsearchConfig } from './elasticsearch_config'; -const MockClient = jest.fn(); -jest.mock('elasticsearch', () => ({ - // Jest types don't include `requireActual` right now. - ...(jest as any).requireActual('elasticsearch'), - Client: MockClient, -})); - -const MockScopedClusterClient = jest.fn(); -jest.mock('./scoped_cluster_client', () => ({ - ScopedClusterClient: MockScopedClusterClient, -})); - -const mockParseElasticsearchClientConfig = jest.fn(); -jest.mock('./elasticsearch_client_config', () => ({ - parseElasticsearchClientConfig: mockParseElasticsearchClientConfig, -})); +import { + MockClient, + mockParseElasticsearchClientConfig, + MockScopedClusterClient, +} from './cluster_client.test.mocks'; import { errors } from 'elasticsearch'; import { get } from 'lodash'; diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts b/src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts new file mode 100644 index 00000000000000..f6c6079822cb5e --- /dev/null +++ b/src/core/server/elasticsearch/elasticsearch_client_config.test.mocks.ts @@ -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 mockReadFileSync = jest.fn(); +jest.mock('fs', () => ({ readFileSync: mockReadFileSync })); diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/elasticsearch_client_config.test.ts index f2eb30f736403b..64fb41cb3e4e5a 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_client_config.test.ts @@ -17,8 +17,7 @@ * under the License. */ -const mockReadFileSync = jest.fn(); -jest.mock('fs', () => ({ readFileSync: mockReadFileSync })); +import { mockReadFileSync } from './elasticsearch_client_config.test.mocks'; import { duration } from 'moment'; import { loggingServiceMock } from '../logging/logging_service.mock'; @@ -67,7 +66,7 @@ Object { }); test('parses fully specified config', () => { - mockReadFileSync.mockImplementation(path => `content-of-${path}`); + mockReadFileSync.mockImplementation((path: string) => `content-of-${path}`); const elasticsearchConfig: ElasticsearchClientConfig = { apiVersion: 'v7.0.0', @@ -607,7 +606,7 @@ Object { }); test('#ignoreCertAndKey = true', () => { - mockReadFileSync.mockImplementation(path => `content-of-${path}`); + mockReadFileSync.mockImplementation((path: string) => `content-of-${path}`); expect( parseElasticsearchClientConfig( diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index bbd7fda86c5e44..57157adc2fac58 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { BehaviorSubject } from 'rxjs'; import { ClusterClient } from './cluster_client'; import { ElasticsearchConfig } from './elasticsearch_config'; diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts new file mode 100644 index 00000000000000..e87913a3c5e4ff --- /dev/null +++ b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts @@ -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 MockClusterClient = jest.fn(); +jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.ts b/src/core/server/elasticsearch/elasticsearch_service.test.ts index f880e318e71732..0697d9152f0a91 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.ts @@ -19,8 +19,7 @@ import { first } from 'rxjs/operators'; -const MockClusterClient = jest.fn(); -jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); +import { MockClusterClient } from './elasticsearch_service.test.mocks'; import { BehaviorSubject, combineLatest } from 'rxjs'; import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config'; diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index f246ff6634b31e..bc9a42b26fdff6 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { Server, ServerOptions } from 'hapi'; import { HttpService } from './http_service'; diff --git a/src/core/server/http/http_service.test.mocks.ts b/src/core/server/http/http_service.test.mocks.ts new file mode 100644 index 00000000000000..a0d7ff5069eb0b --- /dev/null +++ b/src/core/server/http/http_service.test.mocks.ts @@ -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 const mockHttpServer = jest.fn(); + +jest.mock('./http_server', () => ({ + HttpServer: mockHttpServer, +})); diff --git a/src/core/server/http/http_service.test.ts b/src/core/server/http/http_service.test.ts index 6ed3d13221dc20..6c38162a0b7f92 100644 --- a/src/core/server/http/http_service.test.ts +++ b/src/core/server/http/http_service.test.ts @@ -17,11 +17,7 @@ * under the License. */ -const mockHttpServer = jest.fn(); - -jest.mock('./http_server', () => ({ - HttpServer: mockHttpServer, -})); +import { mockHttpServer } from './http_service.test.mocks'; import { noop } from 'lodash'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/server/index.test.mocks.ts b/src/core/server/index.test.mocks.ts new file mode 100644 index 00000000000000..c25772ea46de44 --- /dev/null +++ b/src/core/server/index.test.mocks.ts @@ -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 { httpServiceMock } from './http/http_service.mock'; +export const httpService = httpServiceMock.create(); +jest.doMock('./http/http_service', () => ({ + HttpService: jest.fn(() => httpService), +})); + +export const mockPluginsService = { setup: jest.fn(), stop: jest.fn() }; +jest.doMock('./plugins/plugins_service', () => ({ + PluginsService: jest.fn(() => mockPluginsService), +})); + +import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; +export const elasticsearchService = elasticsearchServiceMock.create(); +jest.doMock('./elasticsearch/elasticsearch_service', () => ({ + ElasticsearchService: jest.fn(() => elasticsearchService), +})); + +export const mockLegacyService = { setup: jest.fn(), stop: jest.fn() }; +jest.mock('./legacy/legacy_service', () => ({ + LegacyService: jest.fn(() => mockLegacyService), +})); diff --git a/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap b/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap index 050184b1f1d52b..76d53b4b1cc5d6 100644 --- a/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap +++ b/src/core/server/legacy/__snapshots__/legacy_service.test.ts.snap @@ -28,6 +28,7 @@ Array [ "valueInBytes": 1073741824, }, }, + "httpsAgent": undefined, "log": Object { "context": Array [ "server", @@ -52,6 +53,7 @@ Array [ "trace": [MockFunction], "warn": [MockFunction], }, + "server": undefined, }, ], ] diff --git a/src/core/server/logging/appenders/appenders.test.mocks.ts b/src/core/server/logging/appenders/appenders.test.mocks.ts new file mode 100644 index 00000000000000..551a4ac1bedc34 --- /dev/null +++ b/src/core/server/logging/appenders/appenders.test.mocks.ts @@ -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 mockCreateLayout = jest.fn(); +jest.mock('../layouts/layouts', () => { + const { schema } = require('@kbn/config-schema'); + return { + Layouts: { + configSchema: schema.object({ kind: schema.literal('mock') }), + create: mockCreateLayout, + }, + }; +}); diff --git a/src/core/server/logging/appenders/appenders.test.ts b/src/core/server/logging/appenders/appenders.test.ts index df528f4c58cd5a..7cfd2158be3389 100644 --- a/src/core/server/logging/appenders/appenders.test.ts +++ b/src/core/server/logging/appenders/appenders.test.ts @@ -17,16 +17,7 @@ * under the License. */ -const mockCreateLayout = jest.fn(); -jest.mock('../layouts/layouts', () => { - const { schema } = require('@kbn/config-schema'); - return { - Layouts: { - configSchema: schema.object({ kind: schema.literal('mock') }), - create: mockCreateLayout, - }, - }; -}); +import { mockCreateLayout } from './appenders.test.mocks'; import { LegacyAppender } from '../../legacy/logging/appenders/legacy_appender'; import { Appenders } from './appenders'; diff --git a/src/core/server/logging/appenders/file/file_appender.test.mocks.ts b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts new file mode 100644 index 00000000000000..a4e4532882f520 --- /dev/null +++ b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts @@ -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. + */ + +jest.mock('../../layouts/layouts', () => { + const { schema } = require('@kbn/config-schema'); + return { + Layouts: { + configSchema: schema.object({ + kind: schema.literal('mock'), + }), + }, + }; +}); + +export const mockCreateWriteStream = jest.fn(); +jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream })); diff --git a/src/core/server/logging/appenders/file/file_appender.test.ts b/src/core/server/logging/appenders/file/file_appender.test.ts index 1d9ef33995955a..fccca629f7d60f 100644 --- a/src/core/server/logging/appenders/file/file_appender.test.ts +++ b/src/core/server/logging/appenders/file/file_appender.test.ts @@ -17,19 +17,7 @@ * under the License. */ -jest.mock('../../layouts/layouts', () => { - const { schema } = require('@kbn/config-schema'); - return { - Layouts: { - configSchema: schema.object({ - kind: schema.literal('mock'), - }), - }, - }; -}); - -const mockCreateWriteStream = jest.fn(); -jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream })); +import { mockCreateWriteStream } from './file_appender.test.mocks'; import { LogLevel } from '../../log_level'; import { LogRecord } from '../../log_record'; diff --git a/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts b/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts new file mode 100644 index 00000000000000..d92465e4dd4971 --- /dev/null +++ b/src/core/server/plugins/discovery/plugin_discovery.test.mocks.ts @@ -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. + */ + +export const mockReaddir = jest.fn(); +export const mockReadFile = jest.fn(); +export const mockStat = jest.fn(); +jest.mock('fs', () => ({ + readdir: mockReaddir, + readFile: mockReadFile, + stat: mockStat, +})); + +export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../../../package.json', () => mockPackage); diff --git a/src/core/server/plugins/discovery/plugin_discovery.test.ts b/src/core/server/plugins/discovery/plugin_discovery.test.ts index 266ad1780d47f7..ac02a21cbe7a76 100644 --- a/src/core/server/plugins/discovery/plugin_discovery.test.ts +++ b/src/core/server/plugins/discovery/plugin_discovery.test.ts @@ -17,17 +17,7 @@ * under the License. */ -const mockReaddir = jest.fn(); -const mockReadFile = jest.fn(); -const mockStat = jest.fn(); -jest.mock('fs', () => ({ - readdir: mockReaddir, - readFile: mockReadFile, - stat: mockStat, -})); - -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../../package.json', () => mockPackage); +import { mockPackage, mockReaddir, mockReadFile, mockStat } from './plugin_discovery.test.mocks'; import { resolve } from 'path'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts new file mode 100644 index 00000000000000..eb8dc1e6095826 --- /dev/null +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts @@ -0,0 +1,22 @@ +/* + * 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 mockReadFile = jest.fn(); +const mockStat = jest.fn(); +jest.mock('fs', () => ({ readFile: mockReadFile, stat: mockStat })); diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts index d6012e4a5e2e43..082cd82e5e1f00 100644 --- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts @@ -19,9 +19,7 @@ import { PluginDiscoveryErrorType } from './plugin_discovery_error'; -const mockReadFile = jest.fn(); -const mockStat = jest.fn(); -jest.mock('fs', () => ({ readFile: mockReadFile, stat: mockStat })); +import { mockReadFile } from './plugin_manifest_parser.test.mocks'; import { resolve } from 'path'; import { parseManifest } from './plugin_manifest_parser'; diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 284e9e10cb7b85..2f2a73668a59df 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -30,15 +30,15 @@ import { createPluginInitializerContext, createPluginSetupContext } from './plug const mockPluginInitializer = jest.fn(); const logger = loggingServiceMock.create(); -jest.mock( +jest.doMock( join('plugin-with-initializer-path', 'server'), () => ({ plugin: mockPluginInitializer }), { virtual: true } ); -jest.mock(join('plugin-without-initializer-path', 'server'), () => ({}), { +jest.doMock(join('plugin-without-initializer-path', 'server'), () => ({}), { virtual: true, }); -jest.mock(join('plugin-with-wrong-initializer-path', 'server'), () => ({ plugin: {} }), { +jest.doMock(join('plugin-with-wrong-initializer-path', 'server'), () => ({ plugin: {} }), { virtual: true, }); diff --git a/src/core/server/plugins/plugins_service.test.mocks.ts b/src/core/server/plugins/plugins_service.test.mocks.ts new file mode 100644 index 00000000000000..13b492e382d676 --- /dev/null +++ b/src/core/server/plugins/plugins_service.test.mocks.ts @@ -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 mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); +jest.mock('../../../legacy/utils/package_json', () => ({ pkg: mockPackage })); + +export const mockDiscover = jest.fn(); +jest.mock('./discovery/plugins_discovery', () => ({ discover: mockDiscover })); + +jest.mock('./plugins_system'); diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index 553cb8a0313899..2a3ce3a4f88d54 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -17,13 +17,7 @@ * under the License. */ -const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../legacy/utils/package_json', () => ({ pkg: mockPackage })); - -const mockDiscover = jest.fn(); -jest.mock('./discovery/plugins_discovery', () => ({ discover: mockDiscover })); - -jest.mock('./plugins_system'); +import { mockDiscover, mockPackage } from './plugins_service.test.mocks'; import { resolve } from 'path'; import { BehaviorSubject, from } from 'rxjs'; diff --git a/src/core/server/plugins/plugins_system.test.mocks.ts b/src/core/server/plugins/plugins_system.test.mocks.ts new file mode 100644 index 00000000000000..9bcbba892fa2ad --- /dev/null +++ b/src/core/server/plugins/plugins_system.test.mocks.ts @@ -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. + */ + +export const mockCreatePluginSetupContext = jest.fn(); +jest.mock('./plugin_context', () => ({ + createPluginSetupContext: mockCreatePluginSetupContext, +})); diff --git a/src/core/server/plugins/plugins_system.test.ts b/src/core/server/plugins/plugins_system.test.ts index 2df8b8301b0ef4..3202a7697bd60d 100644 --- a/src/core/server/plugins/plugins_system.test.ts +++ b/src/core/server/plugins/plugins_system.test.ts @@ -17,16 +17,12 @@ * under the License. */ -import { CoreContext } from '../core_context'; - -const mockCreatePluginSetupContext = jest.fn(); -jest.mock('./plugin_context', () => ({ - createPluginSetupContext: mockCreatePluginSetupContext, -})); +import { mockCreatePluginSetupContext } from './plugins_system.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config'; import { getEnvOptions } from '../config/__mocks__/env'; +import { CoreContext } from '../core_context'; import { elasticsearchServiceMock } from '../elasticsearch/elasticsearch_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { Plugin, PluginName } from './plugin'; diff --git a/src/core/server/root/index.test.mocks.ts b/src/core/server/root/index.test.mocks.ts new file mode 100644 index 00000000000000..602fa2368a766b --- /dev/null +++ b/src/core/server/root/index.test.mocks.ts @@ -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. + */ + +import { loggingServiceMock } from '../logging/logging_service.mock'; +export const logger = loggingServiceMock.create(); +jest.doMock('../logging', () => ({ + LoggingService: jest.fn(() => logger), +})); + +import { configServiceMock } from '../config/config_service.mock'; +export const configService = configServiceMock.create(); +jest.doMock('../config/config_service', () => ({ + ConfigService: jest.fn(() => configService), +})); + +export const mockServer = { setup: jest.fn(), stop: jest.fn() }; +jest.mock('../server', () => ({ Server: jest.fn(() => mockServer) })); diff --git a/src/core/server/root/index.test.ts b/src/core/server/root/index.test.ts index b5915debfe6a43..4eba2133dce285 100644 --- a/src/core/server/root/index.test.ts +++ b/src/core/server/root/index.test.ts @@ -17,20 +17,7 @@ * under the License. */ -import { loggingServiceMock } from '../logging/logging_service.mock'; -const logger = loggingServiceMock.create(); -jest.mock('../logging', () => ({ - LoggingService: jest.fn(() => logger), -})); - -import { configServiceMock } from '../config/config_service.mock'; -const configService = configServiceMock.create(); -jest.mock('../config/config_service', () => ({ - ConfigService: jest.fn(() => configService), -})); - -const mockServer = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('../server', () => ({ Server: jest.fn(() => mockServer) })); +import { configService, logger, mockServer } from './index.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { filter, first } from 'rxjs/operators'; diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts index a3bfa8db21c447..cbfdbbc3bc00d0 100644 --- a/src/core/server/server.test.ts +++ b/src/core/server/server.test.ts @@ -16,27 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { httpServiceMock } from './http/http_service.mock'; -const httpService = httpServiceMock.create(); -jest.mock('./http/http_service', () => ({ - HttpService: jest.fn(() => httpService), -})); - -const mockPluginsService = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('./plugins/plugins_service', () => ({ - PluginsService: jest.fn(() => mockPluginsService), -})); - -import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; -const elasticsearchService = elasticsearchServiceMock.create(); -jest.mock('./elasticsearch/elasticsearch_service', () => ({ - ElasticsearchService: jest.fn(() => elasticsearchService), -})); - -const mockLegacyService = { setup: jest.fn(), stop: jest.fn() }; -jest.mock('./legacy/legacy_service', () => ({ - LegacyService: jest.fn(() => mockLegacyService), -})); + +import { + elasticsearchService, + httpService, + mockLegacyService, + mockPluginsService, +} from './index.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { Env } from './config'; diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js index cda00064162f29..bb450dcd006bc5 100644 --- a/src/dev/build/build_distributables.js +++ b/src/dev/build/build_distributables.js @@ -47,8 +47,8 @@ import { RemovePackageJsonDepsTask, RemoveWorkspacesTask, TranspileBabelTask, - TranspileTypescriptTask, TranspileScssTask, + TypecheckTypescriptTask, UpdateLicenseFileTask, VerifyEnvTask, VerifyExistingNodeBuildsTask, @@ -107,15 +107,14 @@ export async function buildDistributables(options) { * run platform-generic build tasks */ await run(CopySourceTask); + await run(TypecheckTypescriptTask); await run(CreateEmptyDirsAndFilesTask); await run(CreateReadmeTask); await run(TranspileBabelTask); - await run(TranspileTypescriptTask); await run(BuildPackagesTask); await run(CreatePackageJsonTask); await run(InstallDependenciesTask); await run(RemoveWorkspacesTask); - await run(CleanTypescriptTask); await run(CleanPackagesTask); await run(CreateNoticeFileTask); await run(UpdateLicenseFileTask); @@ -123,6 +122,7 @@ export async function buildDistributables(options) { await run(TranspileScssTask); await run(OptimizeBuildTask); await run(CleanClientModulesOnDLLTask); + await run(CleanTypescriptTask); await run(CleanExtraFilesFromModulesTask); await run(CleanEmptyFoldersTask); diff --git a/src/dev/build/tasks/copy_source_task.js b/src/dev/build/tasks/copy_source_task.js index 18ca6492f08c31..01b31b51a060dd 100644 --- a/src/dev/build/tasks/copy_source_task.js +++ b/src/dev/build/tasks/copy_source_task.js @@ -28,7 +28,8 @@ export const CopySourceTask = { select: [ 'yarn.lock', 'src/**', - '!src/**/*.test.{js,ts,tsx}', + '!src/**/*.{test,test.mocks,mock}.{js,ts,tsx}', + '!src/**/mocks.ts', // special file who imports .mock files '!src/**/{__tests__,__snapshots__}/**', '!src/test_utils/**', '!src/fixtures/**', diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js index ecf86d6af23eb6..acf4680fd6f427 100644 --- a/src/dev/build/tasks/index.js +++ b/src/dev/build/tasks/index.js @@ -33,7 +33,7 @@ export * from './notice_file_task'; export * from './optimize_task'; export * from './os_packages'; export * from './transpile_babel_task'; -export * from './transpile_typescript_task'; +export * from './typecheck_typescript_task'; export * from './transpile_scss_task'; export * from './verify_env_task'; export * from './write_sha_sums_task'; diff --git a/src/dev/build/tasks/transpile_babel_task.js b/src/dev/build/tasks/transpile_babel_task.js index 1ea3d815839180..c6d762be9d732e 100644 --- a/src/dev/build/tasks/transpile_babel_task.js +++ b/src/dev/build/tasks/transpile_babel_task.js @@ -22,31 +22,59 @@ import vfs from 'vinyl-fs'; import { createPromiseFromStreams } from '../../../legacy/utils'; +const transpileWithBabel = async (srcGlobs, build, presets) => { + const buildRoot = build.resolvePath(); + + await createPromiseFromStreams([ + vfs.src( + srcGlobs.concat([ + '!**/*.d.ts', + '!packages/**', + '!**/node_modules/**', + '!**/bower_components/**', + '!**/__tests__/**', + ]), + { + cwd: buildRoot, + } + ), + + gulpBabel({ + babelrc: false, + presets, + }), + + vfs.dest(buildRoot), + ]); +}; + export const TranspileBabelTask = { description: 'Transpiling sources with babel', async run(config, log, build) { - await createPromiseFromStreams([ - vfs.src( - [ - '**/*.js', - '!packages/**', - '!**/public/**', - '!**/node_modules/**', - '!**/bower_components/**', - '!**/__tests__/**', - ], - { - cwd: build.resolvePath(), - } - ), - - gulpBabel({ - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/node_preset')], - }), - - vfs.dest(build.resolvePath()), - ]); + // Transpile server code + await transpileWithBabel( + [ + '**/*.{js,ts,tsx}', + '!**/public/**', + ], + build, + [ + require.resolve('@kbn/babel-preset/node_preset') + ] + ); + + // Transpile client code + // NOTE: For the client, as we have the optimizer, we are only + // pre-transpiling the typescript based files + await transpileWithBabel( + [ + '**/public/**/*.{ts,tsx}', + ], + build, + [ + require.resolve('@kbn/babel-preset/webpack_preset') + ] + ); }, }; diff --git a/src/dev/build/tasks/transpile_typescript_task.js b/src/dev/build/tasks/typecheck_typescript_task.js similarity index 85% rename from src/dev/build/tasks/transpile_typescript_task.js rename to src/dev/build/tasks/typecheck_typescript_task.js index 735d6c17afec50..bbdc5f69be8b47 100644 --- a/src/dev/build/tasks/transpile_typescript_task.js +++ b/src/dev/build/tasks/typecheck_typescript_task.js @@ -20,22 +20,13 @@ import { exec, write } from '../lib'; import { Project } from '../../typescript'; -export const TranspileTypescriptTask = { - description: 'Transpiling sources with typescript compiler', +export const TypecheckTypescriptTask = { + description: 'Typechecking sources with typescript compiler', async run(config, log, build) { // these projects are built in the build folder - const defaultProject = new Project(build.resolvePath('tsconfig.json')); const browserProject = new Project(build.resolvePath('tsconfig.browser.json')); - - // update the default config to exclude **/public/**/* files - await write(defaultProject.tsConfigPath, JSON.stringify({ - ...defaultProject.config, - exclude: [ - ...defaultProject.config.exclude, - 'src/**/public/**/*' - ] - })); + const defaultProject = new Project(build.resolvePath('tsconfig.json')); // update the browser config file to include **/public/**/* files await write(browserProject.tsConfigPath, JSON.stringify({ @@ -47,21 +38,28 @@ export const TranspileTypescriptTask = { ] })); + // update the default config to exclude **/public/**/* files + await write(defaultProject.tsConfigPath, JSON.stringify({ + ...defaultProject.config, + exclude: [ + ...defaultProject.config.exclude, + 'src/**/public/**/*' + ] + })); + const projects = [ - // Browser needs to be compiled before server code so that any shared code - // is compiled to the lowest common denominator (server's CommonJS format) - // which can be supported by both environments. browserProject.tsConfigPath, defaultProject.tsConfigPath, ]; // compile each typescript config file for (const tsConfigPath of projects) { - log.info(`Compiling`, tsConfigPath, 'project'); + log.info(`Typechecking`, tsConfigPath, 'project'); await exec( log, require.resolve('typescript/bin/tsc'), [ + '--noEmit', '--pretty', 'true', '--project', tsConfigPath, ], diff --git a/src/dev/i18n/integrate_locale_files.test.mocks.ts b/src/dev/i18n/integrate_locale_files.test.mocks.ts new file mode 100644 index 00000000000000..e84ca068c067ee --- /dev/null +++ b/src/dev/i18n/integrate_locale_files.test.mocks.ts @@ -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 mockWriteFileAsync = jest.fn(); +export const mockMakeDirAsync = jest.fn(); +jest.mock('./utils', () => ({ + // Jest typings don't define `requireActual` for some reason. + ...(jest as any).requireActual('./utils'), + writeFileAsync: mockWriteFileAsync, + makeDirAsync: mockMakeDirAsync, +})); diff --git a/src/dev/i18n/integrate_locale_files.test.ts b/src/dev/i18n/integrate_locale_files.test.ts index 050f16f3d33447..7d7d1ba7446849 100644 --- a/src/dev/i18n/integrate_locale_files.test.ts +++ b/src/dev/i18n/integrate_locale_files.test.ts @@ -17,14 +17,7 @@ * under the License. */ -const mockWriteFileAsync = jest.fn(); -const mockMakeDirAsync = jest.fn(); -jest.mock('./utils', () => ({ - // Jest typings don't define `requireActual` for some reason. - ...(jest as any).requireActual('./utils'), - writeFileAsync: mockWriteFileAsync, - makeDirAsync: mockMakeDirAsync, -})); +import { mockMakeDirAsync, mockWriteFileAsync } from './integrate_locale_files.test.mocks'; import path from 'path'; import { integrateLocaleFiles, verifyMessages } from './integrate_locale_files'; diff --git a/src/dev/jest/babel_transform.js b/src/dev/jest/babel_transform.js index 7bdba8ae7fa152..0796cf859d4ef0 100644 --- a/src/dev/jest/babel_transform.js +++ b/src/dev/jest/babel_transform.js @@ -22,5 +22,5 @@ const babelJest = require('babel-jest'); module.exports = babelJest.createTransformer({ presets: [ require.resolve('@kbn/babel-preset/node_preset') - ] + ], }); diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 1427624f0ce98a..840510815d34df 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -59,11 +59,6 @@ export default { coverageReporters: [ 'html', ], - globals: { - 'ts-jest': { - skipBabel: true, - }, - }, moduleFileExtensions: [ 'js', 'json', @@ -83,8 +78,7 @@ export default { 'integration_tests/' ], transform: { - '^.+\\.js$': '/src/dev/jest/babel_transform.js', - '^.+\\.tsx?$': '/src/dev/jest/ts_transform.js', + '^.+\\.(js|tsx?)$': '/src/dev/jest/babel_transform.js', '^.+\\.txt?$': 'jest-raw-loader', '^.+\\.html?$': 'jest-raw-loader', }, diff --git a/src/dev/jest/setup/babel_polyfill.js b/src/dev/jest/setup/babel_polyfill.js index 38e1cfbcdd7216..58325c1a67f94f 100644 --- a/src/dev/jest/setup/babel_polyfill.js +++ b/src/dev/jest/setup/babel_polyfill.js @@ -18,6 +18,6 @@ */ // Note: In theory importing the polyfill should not be needed, as Babel should -// include the necessary polyfills when using `babel-preset-env`, but for some +// include the necessary polyfills when using `@babel/preset-env`, but for some // reason it did not work. See https://github.com/elastic/kibana/issues/14506 import '../../../setup_node_env/babel_register/polyfill'; diff --git a/src/dev/jest/ts_transform.ts b/src/dev/jest/ts_transform.ts deleted file mode 100644 index ed366bcd091a0b..00000000000000 --- a/src/dev/jest/ts_transform.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 TsJest from 'ts-jest'; - -import { getTsProjectForAbsolutePath } from '../typescript'; - -const DEFAULT_TS_CONFIG_PATH = require.resolve('../../../tsconfig.json'); -const DEFAULT_BROWSER_TS_CONFIG_PATH = require.resolve('../../../tsconfig.browser.json'); - -function extendJestConfigJSON(jestConfigJSON: string, filePath: string) { - const jestConfig = JSON.parse(jestConfigJSON) as jest.ProjectConfig; - return JSON.stringify(extendJestConfig(jestConfig, filePath)); -} - -function extendJestConfig(jestConfig: jest.ProjectConfig, filePath: string) { - let tsConfigFile = getTsProjectForAbsolutePath(filePath).tsConfigPath; - - // swap ts config file for jest tests - if (tsConfigFile === DEFAULT_BROWSER_TS_CONFIG_PATH) { - tsConfigFile = DEFAULT_TS_CONFIG_PATH; - } - - return { - ...jestConfig, - globals: { - ...(jestConfig.globals || {}), - 'ts-jest': { - skipBabel: true, - tsConfigFile, - }, - }, - }; -} - -module.exports = { - canInstrument: true, - - process( - src: string, - filePath: jest.Path, - jestConfig: jest.ProjectConfig, - transformOptions: jest.TransformOptions - ) { - const extendedConfig = extendJestConfig(jestConfig, filePath); - return TsJest.process(src, filePath, extendedConfig, transformOptions); - }, - - getCacheKey( - src: string, - filePath: string, - jestConfigJSON: string, - transformOptions: jest.TransformOptions - ) { - const extendedConfigJSON = extendJestConfigJSON(jestConfigJSON, filePath); - return TsJest.getCacheKey!(src, filePath, extendedConfigJSON, transformOptions); - }, -}; diff --git a/src/dev/license_checker/config.js b/src/dev/license_checker/config.js index 9c6fa7767ee1e9..879c2147ccb11b 100644 --- a/src/dev/license_checker/config.js +++ b/src/dev/license_checker/config.js @@ -105,5 +105,5 @@ export const LICENSE_OVERRIDES = { 'walk@2.3.9': ['MIT'], // TODO remove this once we upgrade past or equal to v1.0.2 - 'babel-plugin-mock-imports@0.0.5': ['MIT'] + 'babel-plugin-mock-imports@1.0.1': ['MIT'] }; diff --git a/src/dev/mocha/run_mocha_cli.js b/src/dev/mocha/run_mocha_cli.js index d24f9a06eafdde..299a910127d40d 100644 --- a/src/dev/mocha/run_mocha_cli.js +++ b/src/dev/mocha/run_mocha_cli.js @@ -43,7 +43,7 @@ export function runMochaCli() { // check that we aren't leaking any globals process.argv.push('--check-leaks'); // prevent globals injected from canvas plugins from triggering leak check - process.argv.push('--globals', 'core,regeneratorRuntime,_'); + process.argv.push('--globals', '__core-js_shared__,core,_, '); // ensure that mocha requires the setup_node_env script process.argv.push('--require', require.resolve('../../setup_node_env')); diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index 540441ab6b8de6..7ef3419751be54 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -35,6 +35,9 @@ export const PROJECTS = [ ...glob .sync('packages/*/tsconfig.json', { cwd: REPO_ROOT }) .map(path => new Project(resolve(REPO_ROOT, path))), + ...glob + .sync('test/plugin_functional/plugins/*/tsconfig.json', { cwd: REPO_ROOT }) + .map(path => new Project(resolve(REPO_ROOT, path))), ]; export function filterProjectsByFlag(projectFlag?: string) { diff --git a/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap b/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap index fdd47c581b7f57..522a12b4ec84f8 100644 --- a/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap +++ b/src/legacy/core_plugins/inspector_views/public/data/__snapshots__/data_view.test.js.snap @@ -222,6 +222,8 @@ exports[`Inspector Data View component should render loading state 1`] = ` }, "_eventsCount": 1, "_maxListeners": undefined, + "tabular": undefined, + "tabularOptions": undefined, }, } } diff --git a/src/legacy/core_plugins/interpreter/common/types/register.js b/src/legacy/core_plugins/interpreter/common/types/register.js index 17b03f0229672d..582843c91f83bb 100644 --- a/src/legacy/core_plugins/interpreter/common/types/register.js +++ b/src/legacy/core_plugins/interpreter/common/types/register.js @@ -17,7 +17,7 @@ * under the License. */ -import 'babel-polyfill'; +import '@babel/polyfill'; import { typeSpecs } from './index'; // eslint-disable-next-line no-undef diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap index bc0bdddfdbc539..aa33eb4ab1d02b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -1125,10 +1125,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1` className="euiScreenReaderOnly" > - - +

- - +

- + - + @@ -2595,7 +2592,7 @@ exports[`NewVisModal should render as expected 1`] = `

- - +

- - +

- + - + diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts new file mode 100644 index 00000000000000..04c99a1547ba93 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.mocks.ts @@ -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 settingsGet = jest.fn(); + +jest.doMock('ui/chrome', () => ({ + getUiSettingsClient: () => ({ + get: settingsGet, + }), +})); diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx index dd357d70f8a0ac..fbb3faf7b3564d 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx @@ -20,13 +20,7 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -const settingsGet = jest.fn(); - -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: () => ({ - get: settingsGet, - }), -})); +import { settingsGet } from './new_vis_modal.test.mocks'; import { NewVisModal } from './new_vis_modal'; diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js index 99238fcd1c9ccc..bed96987ac2b12 100644 --- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js +++ b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js @@ -30,7 +30,7 @@ export const createTestEntryTemplate = (defaultUiSettings) => (bundle) => ` */ // import global polyfills before everything else -import 'babel-polyfill'; +import '@babel/polyfill'; import 'custom-event-polyfill'; import 'whatwg-fetch'; import 'abortcontroller-polyfill'; diff --git a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx index d8426805f57ba7..d8aec7997fdbf2 100644 --- a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx +++ b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx @@ -54,6 +54,7 @@ import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderNavControls } from './header_nav_controls'; +import { i18n } from '@kbn/i18n'; import { InjectedIntl, injectI18n } from '@kbn/i18n/react'; import chrome, { NavLink } from 'ui/chrome'; import { HelpExtension } from 'ui/chrome'; @@ -88,10 +89,23 @@ function extendRecentlyAccessedHistoryItem( const href = relativeToAbsolute(chrome.addBasePath(recentlyAccessed.link)); const navLink = navLinks.find(nl => href.startsWith(nl.subUrlBase)); + let titleAndAriaLabel = recentlyAccessed.label; + if (navLink) { + const objectTypeForAriaAppendix = navLink.title; + titleAndAriaLabel = i18n.translate('common.ui.recentLinks.linkItem.screenReaderLabel', { + defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', + values: { + recentlyAccessedItemLinklabel: recentlyAccessed.label, + pageType: objectTypeForAriaAppendix, + }, + }); + } + return { ...recentlyAccessed, href, euiIconType: navLink ? navLink.euiIconType : undefined, + title: titleAndAriaLabel, }; } @@ -248,9 +262,8 @@ class HeaderUI extends Component { }), listItems: recentlyAccessed.map(item => ({ label: truncateRecentItemLabel(item.label), - // TODO: Add what type of app/saved object to title attr - title: `${item.label}`, - 'aria-label': item.label, + title: item.title, + 'aria-label': item.title, href: item.href, iconType: item.euiIconType, })), diff --git a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts index 152fdee9f7fff6..d43f1d16aefd1a 100644 --- a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts +++ b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts @@ -21,3 +21,4 @@ export { ContextMenuPanel } from './context_menu_panel'; export { ContextMenuAction } from './context_menu_action'; export { ContextMenuActionsRegistryProvider } from './context_menu_actions_registry'; export { buildEuiContextMenuPanels } from './build_eui_context_menu_panels'; +export { PanelActionAPI } from './types'; diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap index 8a0efdef72011d..12492b0bb7b68c 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap +++ b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap @@ -14,7 +14,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = ` , + "content": , "data-test-subj": "syntaxTab", "id": "syntax", "name": "Syntax", @@ -23,7 +23,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = ` tabs={ Array [ Object { - "content": , + "content": , "data-test-subj": "syntaxTab", "id": "syntax", "name": "Syntax", diff --git a/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap b/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap index c58cab79fdc4e4..0f078899987683 100644 --- a/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap +++ b/src/legacy/ui/public/query_bar/components/__snapshots__/language_switcher.test.tsx.snap @@ -47,9 +47,7 @@ exports[`LanguageSwitcher should toggle off if language is lucene 1`] = ` >

{ + return { + getBasePath: () => `foo`, + getUiSettingsClient: () => { + return { + get: (key: string) => { + switch (key) { + case 'history:limit': + return 10; + default: + throw new Error(`Unexpected config key: ${key}`); + } + }, + }; + }, + }; +}); + +export const mockPersistedLog = { + add: jest.fn(), + get: jest.fn(() => ['response:200']), +}; + +export const mockPersistedLogFactory = jest.fn, any>(() => { + return mockPersistedLog; +}); + +export const mockGetAutocompleteSuggestions = jest.fn(() => Promise.resolve([])); +const mockAutocompleteProvider = jest.fn(() => mockGetAutocompleteSuggestions); +export const mockGetAutocompleteProvider = jest.fn(() => mockAutocompleteProvider); + +jest.mock('ui/chrome', () => mockChromeFactory()); +jest.mock('../../chrome', () => mockChromeFactory()); +jest.mock('ui/persisted_log', () => ({ + PersistedLog: mockPersistedLogFactory, +})); +jest.mock('../../metadata', () => ({ + metadata: { + branch: 'foo', + }, +})); +jest.mock('../../autocomplete_providers', () => ({ + getAutocompleteProvider: mockGetAutocompleteProvider, +})); + +import _ from 'lodash'; +// Using doMock to avoid hoisting so that I can override only the debounce method in lodash +jest.doMock('lodash', () => ({ + ..._, + debounce: (func: () => any) => func, +})); diff --git a/src/legacy/ui/public/query_bar/components/query_bar.test.tsx b/src/legacy/ui/public/query_bar/components/query_bar.test.tsx index fdcfb770439193..f6947574bee160 100644 --- a/src/legacy/ui/public/query_bar/components/query_bar.test.tsx +++ b/src/legacy/ui/public/query_bar/components/query_bar.test.tsx @@ -17,57 +17,12 @@ * under the License. */ -const mockChromeFactory = jest.fn(() => { - return { - getBasePath: () => `foo`, - getUiSettingsClient: () => { - return { - get: (key: string) => { - switch (key) { - case 'history:limit': - return 10; - default: - throw new Error(`Unexpected config key: ${key}`); - } - }, - }; - }, - }; -}); - -const mockPersistedLog = { - add: jest.fn(), - get: jest.fn(() => ['response:200']), -}; - -const mockPersistedLogFactory = jest.fn, any>(() => { - return mockPersistedLog; -}); - -const mockGetAutocompleteSuggestions = jest.fn(() => Promise.resolve([])); -const mockAutocompleteProvider = jest.fn(() => mockGetAutocompleteSuggestions); -const mockGetAutocompleteProvider = jest.fn(() => mockAutocompleteProvider); - -jest.mock('ui/chrome', () => mockChromeFactory()); -jest.mock('../../chrome', () => mockChromeFactory()); -jest.mock('ui/persisted_log', () => ({ - PersistedLog: mockPersistedLogFactory, -})); -jest.mock('../../metadata', () => ({ - metadata: { - branch: 'foo', - }, -})); -jest.mock('../../autocomplete_providers', () => ({ - getAutocompleteProvider: mockGetAutocompleteProvider, -})); - -import _ from 'lodash'; -// Using doMock to avoid hoisting so that I can override only the debounce method in lodash -jest.doMock('lodash', () => ({ - ..._, - debounce: (func: () => any) => func, -})); +import { + mockGetAutocompleteProvider, + mockGetAutocompleteSuggestions, + mockPersistedLog, + mockPersistedLogFactory, +} from 'ui/query_bar/components/query_bar.test.mocks'; import { EuiFieldText } from '@elastic/eui'; import React from 'react'; diff --git a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap index 6388a57832c0ae..3b51c1db50d00c 100644 --- a/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap +++ b/src/legacy/ui/public/query_bar/components/typeahead/__snapshots__/suggestions_component.test.tsx.snap @@ -16,7 +16,7 @@ exports[`SuggestionsComponent Passing the index should control which suggestion onScroll={[Function]} role="listbox" > - - - - @@ -207,8 +203,7 @@ exports[`should enable saved object export option when objectId is provided 1`] aria-label="Info" content={ diff --git a/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts b/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts new file mode 100644 index 00000000000000..815d2f09150c7a --- /dev/null +++ b/src/legacy/ui/public/utils/subscribe_with_scope.test.mocks.ts @@ -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. + */ + +export const mockFatalError = jest.fn(); +jest.mock('ui/notify/fatal_error', () => ({ + fatalError: mockFatalError, +})); diff --git a/src/legacy/ui/public/utils/subscribe_with_scope.test.ts b/src/legacy/ui/public/utils/subscribe_with_scope.test.ts index a5a3312bad4bfb..077875c5ac6e5b 100644 --- a/src/legacy/ui/public/utils/subscribe_with_scope.test.ts +++ b/src/legacy/ui/public/utils/subscribe_with_scope.test.ts @@ -16,11 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -const mockFatalError = jest.fn(); -jest.mock('ui/notify/fatal_error', () => ({ - fatalError: mockFatalError, -})); +import { mockFatalError } from './subscribe_with_scope.test.mocks'; import * as Rx from 'rxjs'; import { subscribeWithScope } from './subscribe_with_scope'; diff --git a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts index 3e7623b6c25fc9..ab57153755c91e 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts +++ b/src/legacy/ui/public/vis/editors/default/agg_param_editor_props.ts @@ -20,11 +20,13 @@ import { AggParam } from '../../../agg_types'; import { AggConfig } from '../../agg_config'; -interface AggParamEditorProps { +// NOTE: we cannot export the interface with export { InterfaceName } +// as there is currently a bug on babel typescript transform plugin for it +// https://github.com/babel/babel/issues/7641 +// +export interface AggParamEditorProps { agg: AggConfig; aggParam: AggParam; value: T; setValue(value: T): void; } - -export { AggParamEditorProps }; diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts new file mode 100644 index 00000000000000..6adea30c94fb49 --- /dev/null +++ b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.mocks.ts @@ -0,0 +1,67 @@ +/* + * 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. + */ + +jest.useFakeTimers(); + +import { EventEmitter } from 'events'; + +jest.mock('ui/notify', () => ({ + toastNotifications: jest.fn(), +})); + +jest.mock('./utils', () => ({ + queryGeohashBounds: jest.fn(), +})); + +jest.mock('./pipeline_helpers/utilities', () => ({ + getFormat: jest.fn(), + getTableAggs: jest.fn(), +})); + +export const timefilter = new EventEmitter(); +jest.doMock('../../timefilter', () => ({ timefilter })); + +jest.mock('../../inspector', () => ({ + Inspector: { + open: jest.fn(), + isAvailable: jest.fn(), + }, +})); + +export const mockDataLoaderFetch = jest.fn().mockReturnValue({ + as: 'visualization', + value: { + visType: 'histogram', + visData: {}, + visConfig: {}, + params: {}, + }, +}); +const MockDataLoader = class { + public async fetch(data: any) { + return await mockDataLoaderFetch(data); + } +}; + +jest.mock('./pipeline_data_loader', () => ({ + PipelineDataLoader: MockDataLoader, +})); +jest.mock('./visualize_data_loader', () => ({ + VisualizeDataLoader: MockDataLoader, +})); diff --git a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts index 3dc39ba7e2a905..e5a4eb122dc888 100644 --- a/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts +++ b/src/legacy/ui/public/visualize/loader/embedded_visualize_handler.test.ts @@ -16,61 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - -jest.useFakeTimers(); - -import { EventEmitter } from 'events'; +import { mockDataLoaderFetch, timefilter } from './embedded_visualize_handler.test.mocks'; // @ts-ignore import MockState from '../../../../../fixtures/mock_state'; import { RequestHandlerParams, Vis } from '../../vis'; import { VisResponseData } from './types'; -jest.mock('ui/notify', () => ({ - toastNotifications: jest.fn(), -})); - -jest.mock('./utils', () => ({ - queryGeohashBounds: jest.fn(), -})); - -jest.mock('./pipeline_helpers/utilities', () => ({ - getFormat: jest.fn(), - getTableAggs: jest.fn(), -})); - -const timefilter = new EventEmitter(); -jest.mock('../../timefilter', () => ({ timefilter })); - -jest.mock('../../inspector', () => ({ - Inspector: { - open: jest.fn(), - isAvailable: jest.fn(), - }, -})); - -const mockDataLoaderFetch = jest.fn().mockReturnValue({ - as: 'visualization', - value: { - visType: 'histogram', - visData: {}, - visConfig: {}, - params: {}, - }, -}); -const MockDataLoader = class { - public async fetch(data: any) { - return await mockDataLoaderFetch(data); - } -}; - -jest.mock('./pipeline_data_loader', () => ({ - PipelineDataLoader: MockDataLoader, -})); -jest.mock('./visualize_data_loader', () => ({ - VisualizeDataLoader: MockDataLoader, -})); - import { Inspector } from '../../inspector'; import { EmbeddedVisualizeHandler } from './embedded_visualize_handler'; diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts index fe9a36a0e5a634..3617c77e42b0f8 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities.ts @@ -31,7 +31,7 @@ import { fieldFormats } from '../../../registry/field_formats'; const config = chrome.getUiSettingsClient(); const defaultFormat = { convert: identity }; -const getConfig = (...args: any[]): any => (config.get as any)(...args); +const getConfig = (...args: any[]): any => config.get(...args); const getFieldFormat = (id: string, params: object) => { const Format = fieldFormats.byId[id]; diff --git a/src/legacy/ui/ui_bundles/app_entry_template.js b/src/legacy/ui/ui_bundles/app_entry_template.js index 2d92dc30556fb9..625ce5e381d216 100644 --- a/src/legacy/ui/ui_bundles/app_entry_template.js +++ b/src/legacy/ui/ui_bundles/app_entry_template.js @@ -33,7 +33,7 @@ import 'dll/set_csp_nonce'; __webpack_nonce__ = window.__kbnNonce__; // import global polyfills -import 'babel-polyfill'; +import '@babel/polyfill'; import 'custom-event-polyfill'; import 'whatwg-fetch'; import 'abortcontroller-polyfill'; diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js index b260f57df33118..bb130e3869509a 100644 --- a/src/optimize/base_optimizer.js +++ b/src/optimize/base_optimizer.js @@ -123,10 +123,6 @@ export default class BaseOptimizer { BABEL_PRESET_PATH ]; - const nonDistributableOnlyModules = !IS_KIBANA_DISTRIBUTABLE - ? ['ts-loader'] - : []; - threadLoader.warmup( // pool options, like passed to loader options // must match loader options to boot the correct pool @@ -134,7 +130,6 @@ export default class BaseOptimizer { [ // modules to load on the pool ...baseModules, - ...nonDistributableOnlyModules ] ); } @@ -368,7 +363,7 @@ export default class BaseOptimizer { } }, { - resource: createSourceFileResourceSelector(/\.js$/), + resource: createSourceFileResourceSelector(/\.(js|tsx?)$/), use: maybeAddCacheLoader('babel', [ { loader: 'thread-loader', @@ -394,7 +389,7 @@ export default class BaseOptimizer { }, resolve: { - extensions: ['.js', '.json'], + extensions: ['.js', '.ts', '.tsx', '.json'], mainFields: ['browser', 'browserify', 'main'], modules: [ 'webpackShims', @@ -429,47 +424,6 @@ export default class BaseOptimizer { ] }; - // when running from source transpile TypeScript automatically - const getSourceConfig = () => { - // dev/typescript is deleted from the distributable, so only require it if we actually need the source config - const { Project } = require('../dev/typescript'); - const browserProject = new Project(fromRoot('tsconfig.browser.json')); - - return { - module: { - rules: [ - { - resource: createSourceFileResourceSelector(/\.tsx?$/), - use: maybeAddCacheLoader('typescript', [ - { - loader: 'thread-loader', - options: this.getThreadLoaderPoolConfig() - }, - { - loader: 'ts-loader', - options: { - happyPackMode: true, - transpileOnly: true, - experimentalWatchApi: true, - onlyCompileBundledFiles: true, - configFile: fromRoot('tsconfig.json'), - compilerOptions: { - ...browserProject.config.compilerOptions, - sourceMap: Boolean(this.sourceMaps), - } - } - } - ]), - } - ] - }, - - resolve: { - extensions: ['.ts', '.tsx'], - }, - }; - }; - // We need to add react-addons (and a few other bits) for enzyme to work. // https://github.com/airbnb/enzyme/blob/master/docs/guides/webpack.md const supportEnzymeConfig = { @@ -516,7 +470,7 @@ export default class BaseOptimizer { commonConfig, IS_KIBANA_DISTRIBUTABLE ? isDistributableConfig - : getSourceConfig(), + : {}, this.uiBundles.isDevMode() ? webpackMerge(watchingConfig, supportEnzymeConfig) : productionConfig diff --git a/src/optimize/watch/watch_cache.ts b/src/optimize/watch/watch_cache.ts index 01afed1b2640f3..ab11a8c5d2f118 100644 --- a/src/optimize/watch/watch_cache.ts +++ b/src/optimize/watch/watch_cache.ts @@ -95,16 +95,7 @@ export class WatchCache { await del(this.statePath, { force: true }); // delete everything in optimize/.cache directory - // except ts-node - await del( - await globby( - [ - normalizePosixPath(this.cachePath), - `${normalizePosixPath(`!${this.cachePath}/ts-node/**`)}`, - ], - { dot: true } - ) - ); + await del(await globby([normalizePosixPath(this.cachePath)], { dot: true })); // delete some empty folder that could be left // from the previous cache path reset action diff --git a/src/setup_node_env/babel_register/index.js b/src/setup_node_env/babel_register/index.js index 44b9427ed8e3e2..1574be8937a29e 100644 --- a/src/setup_node_env/babel_register/index.js +++ b/src/setup_node_env/babel_register/index.js @@ -17,16 +17,6 @@ * under the License. */ -// unless we are running a prebuilt/distributable version of -// kibana, automatically transpile typescript to js before babel -if (!global.__BUILT_WITH_BABEL__) { - var resolve = require('path').resolve; - require('ts-node').register({ - transpileOnly: true, - cacheDirectory: resolve(__dirname, '../../../optimize/.cache/ts-node') - }); -} - // register and polyfill need to happen in this // order and in separate files. Checkout each file // for a much more detailed explanation diff --git a/src/setup_node_env/babel_register/polyfill.js b/src/setup_node_env/babel_register/polyfill.js index e72a2eff001ad3..4e92583f830e57 100644 --- a/src/setup_node_env/babel_register/polyfill.js +++ b/src/setup_node_env/babel_register/polyfill.js @@ -17,13 +17,13 @@ * under the License. */ -// `babel-preset-env` looks for and rewrites the following import +// `@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` +// 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 ./index.js -require('babel-polyfill'); +require('@babel/polyfill'); diff --git a/src/setup_node_env/babel_register/register.js b/src/setup_node_env/babel_register/register.js index f0898b245fb0e7..37e39d4685cacb 100644 --- a/src/setup_node_env/babel_register/register.js +++ b/src/setup_node_env/babel_register/register.js @@ -19,13 +19,13 @@ var resolve = require('path').resolve; -// this must happen before `require('babel-register')` and can't be changed +// this must happen before `require('@babel/register')` and can't be changed // once the module has been loaded if (!process.env.BABEL_CACHE_PATH) { process.env.BABEL_CACHE_PATH = resolve(__dirname, '../../../optimize/.babelcache.json'); } -// paths that babel-register should ignore +// paths that @babel/register should ignore var ignore = [ /\/bower_components\//, /\/kbn-pm\/dist\//, @@ -48,10 +48,10 @@ var ignore = [ if (global.__BUILT_WITH_BABEL__) { // when building the Kibana source we replace the statement // `global.__BUILT_WITH_BABEL__` with the value `true` so that - // when babel-register is required for the first time by users + // when @babel/register is required for the first time by users // it will exclude kibana's `src` directory. // - // We still need babel-register for plugins though, we've been + // We still need @babel/register for plugins though, we've been // building their server code at require-time since version 4.2 // TODO: the plugin install process could transpile plugin server code... ignore.push(resolve(__dirname, '../../../src')); @@ -66,10 +66,11 @@ if (global.__BUILT_WITH_BABEL__) { // modifies all future calls to require() to automatically // compile the required source with babel -require('babel-register')({ +require('@babel/register')({ ignore, babelrc: false, presets: [ require.resolve('@kbn/babel-preset/node_preset') ], + extensions: ['.js', '.ts', '.tsx'], }); diff --git a/src/setup_node_env/index.js b/src/setup_node_env/index.js index 6592fa9fd2424a..a3fe8d938ba2bf 100644 --- a/src/setup_node_env/index.js +++ b/src/setup_node_env/index.js @@ -17,5 +17,6 @@ * under the License. */ +require('./root'); require('./node_version_validator'); require('./babel_register'); diff --git a/src/setup_node_env/root/force.js b/src/setup_node_env/root/force.js new file mode 100644 index 00000000000000..5c5370aec6b152 --- /dev/null +++ b/src/setup_node_env/root/force.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. + */ + +module.exports = function (argv) { + var rootIndex = argv.indexOf('--allow-root'); + var force = rootIndex >= 0; + if (force) argv.splice(rootIndex, 1); + return force; +}; diff --git a/src/setup_node_env/root/force.test.js b/src/setup_node_env/root/force.test.js new file mode 100644 index 00000000000000..df013349e57ed2 --- /dev/null +++ b/src/setup_node_env/root/force.test.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +var forceRoot = require('./force'); + +describe('forceRoot', function () { + + it('with flag', function () { + expect(forceRoot(['--allow-root'])).toBeTruthy(); + }); + + it('without flag', function () { + expect(forceRoot(['--foo'])).toBeFalsy(); + + }); + + test('remove argument', function () { + var args = ['--allow-root', 'foo']; + forceRoot(args); + expect(args.includes('--allow-root')).toBeFalsy(); + }); + +}); diff --git a/src/setup_node_env/root/index.js b/src/setup_node_env/root/index.js new file mode 100644 index 00000000000000..5a402dfcb4eeb8 --- /dev/null +++ b/src/setup_node_env/root/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. + */ + +var force = require('./force')(process.argv); + +var uid = process.getuid && process.getuid(); +var isRoot = require('./is_root')(uid); + +if(isRoot && !force) { + console.error('Kibana should not be run as root. Use --allow-root to continue.'); + process.exit(1); +} diff --git a/src/dev/jest/ts_transform.js b/src/setup_node_env/root/is_root.js similarity index 90% rename from src/dev/jest/ts_transform.js rename to src/setup_node_env/root/is_root.js index f097ed2f8076ae..e2eaaf6af51540 100644 --- a/src/dev/jest/ts_transform.js +++ b/src/setup_node_env/root/is_root.js @@ -17,5 +17,6 @@ * under the License. */ -require('../../setup_node_env'); -module.exports = require('./ts_transform.ts'); +module.exports = function (uid) { + return uid === 0; +}; diff --git a/src/setup_node_env/root/is_root.test.js b/src/setup_node_env/root/is_root.test.js new file mode 100644 index 00000000000000..a976299cd5d5b4 --- /dev/null +++ b/src/setup_node_env/root/is_root.test.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. + */ + +var isRoot = require('./is_root'); + + +describe('isRoot', function () { + + test('0 is root', function () { + expect(isRoot(0)).toBeTruthy(); + }); + + test('not 0 is not root', function () { + expect(isRoot(5)).toBeFalsy(); + }); +}); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts similarity index 75% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts index c4aaaa857cecd1..dd069010e0742b 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/index.ts @@ -17,8 +17,15 @@ * under the License. */ -function samplePanelAction(kibana) { +import { resolve } from 'path'; + +// TODO: use something better once https://github.com/elastic/kibana/issues/26555 is +// figured out. +type KibanaPlugin = any; + +function samplePanelAction(kibana: KibanaPlugin) { return new kibana.Plugin({ + publicDir: resolve(__dirname, './public'), uiExports: { contextMenuActions: [ 'plugins/kbn_tp_sample_panel_action/sample_panel_action', @@ -28,9 +35,6 @@ function samplePanelAction(kibana) { }); } -module.exports = function (kibana) { - return [ - samplePanelAction(kibana), - ]; +module.exports = (kibana: KibanaPlugin) => { + return [samplePanelAction(kibana)]; }; - diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index ae68ac4f5c5435..462f5448d7cff1 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -1,13 +1,22 @@ { "name": "kbn_tp_sample_panel_action", "version": "1.0.0", + "main":"target/test/plugin_functional/plugins/kbn_tp_sample_panel_action", "kibana": { "version": "kibana", "templateVersion": "1.0.0" }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "9.4.0", + "@elastic/eui": "9.4.2", "react": "^16.8.0" + }, + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "@kbn/plugin-helpers" : "9.0.2", + "typescript": "^3.3.3333" } -} +} \ No newline at end of file diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx similarity index 93% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx index 1310ff027e35e4..41c867b5526d5c 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx @@ -23,6 +23,7 @@ import { openFlyout } from 'ui/flyout'; import { ContextMenuAction, ContextMenuActionsRegistryProvider, + PanelActionAPI, } from 'ui/embeddable'; class SamplePanelAction extends ContextMenuAction { @@ -33,7 +34,10 @@ class SamplePanelAction extends ContextMenuAction { parentPanelId: 'mainMenu', }); } - onClick({ embeddable }) { + public onClick = ({ embeddable }: PanelActionAPI) => { + if (!embeddable) { + return; + } openFlyout( @@ -47,9 +51,9 @@ class SamplePanelAction extends ContextMenuAction { , { 'data-test-subj': 'samplePanelActionFlyout', - }, + } ); - } + }; } ContextMenuActionsRegistryProvider.register(() => new SamplePanelAction()); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts similarity index 90% rename from test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js rename to test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts index 0b99b7eadb3c79..7092c783125d93 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.js +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts @@ -16,10 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { - ContextMenuAction, - ContextMenuActionsRegistryProvider, -} from 'ui/embeddable'; +import { ContextMenuAction, ContextMenuActionsRegistryProvider } from 'ui/embeddable'; class SamplePanelLink extends ContextMenuAction { constructor() { @@ -29,9 +26,10 @@ class SamplePanelLink extends ContextMenuAction { parentPanelId: 'mainMenu', }); } - getHref() { + + public getHref = () => { return 'https://example.com/kibana/test'; - } + }; } ContextMenuActionsRegistryProvider.register(() => new SamplePanelLink()); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json new file mode 100644 index 00000000000000..aba7203377affa --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "../../../../typings/**/*", + ], + "exclude": [] +} \ No newline at end of file diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh index c9eec36cdc743a..a4bc597316dcb1 100755 --- a/test/scripts/jenkins_ci_group.sh +++ b/test/scripts/jenkins_ci_group.sh @@ -22,6 +22,10 @@ export TEST_BROWSER_HEADLESS=1 "$(FORCE_COLOR=0 yarn bin)/grunt" "run:functionalTests_ciGroup${CI_GROUP}"; if [ "$CI_GROUP" == "1" ]; then - "$(FORCE_COLOR=0 yarn bin)/grunt" run:pluginFunctionalTestsRelease; + # build kbn_tp_sample_panel_action + cd test/plugin_functional/plugins/kbn_tp_sample_panel_action; + yarn build; + cd -; + "$(FORCE_COLOR=0 yarn bin)/grunt" run:pluginFunctionalTestsRelease --from=source; "$(FORCE_COLOR=0 yarn bin)/grunt" run:interpreterFunctionalTestsRelease; fi diff --git a/test/tsconfig.json b/test/tsconfig.json index 5df729fbde21b4..d620d28f3d1de4 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -7,6 +7,10 @@ ] }, "include": [ - "**/*.ts" + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "plugin_functional/plugins/**/*" ] } diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index bf20e88333787c..ad5b2fde1acfef 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -37,8 +37,7 @@ export function createJestConfig({ '**/*.test.{js,ts,tsx}' ], transform: { - '^.+\\.js$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`, - '^.+\\.tsx?$': `${kibanaDirectory}/src/dev/jest/ts_transform.js`, + '^.+\\.(js|tsx?)$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`, }, transformIgnorePatterns: [ '[/\\\\]node_modules[/\\\\].+\\.js$' diff --git a/x-pack/package.json b/x-pack/package.json index 2ad347a2d72840..7655ffdefdcc5c 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -74,11 +74,11 @@ "ansi-colors": "^3.0.5", "ansicolors": "0.3.2", "axios": "^0.18.0", - "babel-jest": "^23.6.0", - "babel-plugin-inline-react-svg": "^0.5.4", - "babel-plugin-mock-imports": "^0.0.5", - "babel-plugin-require-context-hook": "^1.0.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.14", + "babel-jest": "^24.1.0", + "babel-plugin-inline-react-svg": "^1.0.1", + "babel-plugin-mock-imports": "^1.0.1", + "babel-plugin-require-context-hook": "npm:babel-plugin-require-context-hook-babel7@^1.0.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "chalk": "^2.4.1", "chance": "1.0.10", "checksum": "0.1.1", @@ -128,13 +128,16 @@ "supertest-as-promised": "^4.0.2", "tmp": "0.0.31", "tree-kill": "^1.1.0", - "ts-loader": "^5.2.2", "typescript": "^3.3.3333", "vinyl-fs": "^3.0.2", "xml-crypto": "^0.10.1", "yargs": "4.8.1" }, "dependencies": { + "@babel/core": "^7.3.4", + "@babel/polyfill": "^7.2.5", + "@babel/register": "^7.0.0", + "@babel/runtime": "^7.3.4", "@elastic/datemath": "5.0.2", "@elastic/eui": "9.5.0", "@elastic/node-crypto": "0.1.2", @@ -160,11 +163,6 @@ "apollo-server-errors": "^2.0.2", "apollo-server-hapi": "^1.3.6", "axios": "^0.18.0", - "babel-core": "^6.26.3", - "babel-polyfill": "6.20.0", - "babel-preset-es2015": "^6.24.1", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", "base64-js": "^1.2.1", "bluebird": "3.5.3", "boom": "^7.2.0", diff --git a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx index ed5c609cb90039..12198b1a870df1 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/__test__/DiscoverLinks.integration.test.tsx @@ -15,8 +15,6 @@ import { DiscoverErrorLink } from '../DiscoverErrorLink'; import { DiscoverSpanLink } from '../DiscoverSpanLink'; import { DiscoverTransactionLink } from '../DiscoverTransactionLink'; -// NOTE: jest.mock() is broken in TS test files (b/c of ts-jest, I think) -// but using jest's "spies can be stubbed" feature, this works: jest .spyOn(savedObjects, 'getAPMIndexPattern') .mockReturnValue( diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx index 47cffde62612e0..61d2fcf026652b 100644 --- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx @@ -4,18 +4,33 @@ * you may not use this file except in compliance with the Elastic License. */ +jest.mock('../tabConfigConst', () => { + return { + TAB_CONFIG: [ + { + key: 'testProperty', + label: 'testPropertyLabel', + required: false, + presortedKeys: ['name', 'age'] + }, + { + key: 'optionalProperty', + label: 'optionalPropertyLabel', + required: false + }, + { + key: 'requiredProperty', + label: 'requiredPropertyLabel', + required: true + } + ] + }; +}); + import * as propertyConfig from '../tabConfig'; const { getTabsFromObject, sortKeysByConfig } = propertyConfig; describe('tabConfig', () => { - beforeEach(() => { - mockPropertyConfig(); - }); - - afterEach(() => { - unMockPropertyConfig(); - }); - describe('getTabsFromObject', () => { it('should return selected and required keys only', () => { const expectedTabs = [ @@ -64,31 +79,3 @@ describe('tabConfig', () => { }); }); }); - -function mockPropertyConfig() { - // @ts-ignore - propertyConfig.TAB_CONFIG = [ - { - key: 'testProperty', - label: 'testPropertyLabel', - required: false, - presortedKeys: ['name', 'age'] - }, - { - key: 'optionalProperty', - label: 'optionalPropertyLabel', - required: false - }, - { - key: 'requiredProperty', - label: 'requiredPropertyLabel', - required: true - } - ]; -} - -const originalPropertyConfig = propertyConfig.TAB_CONFIG; -function unMockPropertyConfig() { - // @ts-ignore - propertyConfig.TAB_CONFIG = originalPropertyConfig; -} diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts index cb9ce7f8538bc9..2648c2875cd840 100644 --- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts @@ -4,28 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { get, indexBy, uniq } from 'lodash'; import { first, has } from 'lodash'; import { StringMap } from 'x-pack/plugins/apm/typings/common'; import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/ui/APMError'; import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/ui/Transaction'; - -export type PropertyTabKey = - | keyof Transaction - | keyof APMError - | 'transaction.custom' - | 'error.custom'; - -export interface PropertyTab { - key: PropertyTabKey; - label: string; -} - -interface TabConfig extends PropertyTab { - required: boolean; - presortedKeys: string[]; -} +import { + PropertyTab, + PropertyTabKey, + TAB_CONFIG, + TabConfig +} from './tabConfigConst'; export function getTabsFromObject(obj: Transaction | APMError): PropertyTab[] { return TAB_CONFIG.filter( @@ -53,96 +42,4 @@ export function getCurrentTab( return selectedTab ? selectedTab : first(tabs) || {}; } -export const TAB_CONFIG: TabConfig[] = [ - { - key: 'http', - label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', { - defaultMessage: 'HTTP' - }), - required: false, - presortedKeys: [] - }, - { - key: 'host', - label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', { - defaultMessage: 'Host' - }), - required: false, - presortedKeys: ['hostname', 'architecture', 'platform'] - }, - { - key: 'service', - label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', { - defaultMessage: 'Service' - }), - required: false, - presortedKeys: ['runtime', 'framework', 'version'] - }, - { - key: 'process', - label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', { - defaultMessage: 'Process' - }), - required: false, - presortedKeys: ['pid', 'title', 'args'] - }, - { - key: 'agent', - label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', { - defaultMessage: 'Agent' - }), - required: false, - presortedKeys: [] - }, - { - key: 'url', - label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', { - defaultMessage: 'URL' - }), - required: false, - presortedKeys: [] - }, - { - key: 'container', - label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', { - defaultMessage: 'Container' - }), - required: false, - presortedKeys: [] - }, - { - key: 'user', - label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', { - defaultMessage: 'User' - }), - required: true, - presortedKeys: ['id', 'username', 'email'] - }, - { - key: 'labels', - label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', { - defaultMessage: 'Labels' - }), - required: true, - presortedKeys: [] - }, - { - key: 'transaction.custom', - label: i18n.translate( - 'xpack.apm.propertiesTable.tabs.transactionCustomLabel', - { - defaultMessage: 'Custom' - } - ), - required: false, - presortedKeys: [] - }, - { - key: 'error.custom', - label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', { - defaultMessage: 'Custom' - }), - required: false, - presortedKeys: [] - } -]; +export { TAB_CONFIG, TabConfig, PropertyTab, PropertyTabKey }; diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts new file mode 100644 index 00000000000000..95c4f6da9f37e0 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts @@ -0,0 +1,119 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/ui/APMError'; +import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/ui/Transaction'; + +export type PropertyTabKey = + | keyof Transaction + | keyof APMError + | 'transaction.custom' + | 'error.custom'; + +export interface PropertyTab { + key: PropertyTabKey; + label: string; +} + +export interface TabConfig extends PropertyTab { + required: boolean; + presortedKeys: string[]; +} + +export const TAB_CONFIG: TabConfig[] = [ + { + key: 'http', + label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', { + defaultMessage: 'HTTP' + }), + required: false, + presortedKeys: [] + }, + { + key: 'host', + label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', { + defaultMessage: 'Host' + }), + required: false, + presortedKeys: ['hostname', 'architecture', 'platform'] + }, + { + key: 'service', + label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', { + defaultMessage: 'Service' + }), + required: false, + presortedKeys: ['runtime', 'framework', 'version'] + }, + { + key: 'process', + label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', { + defaultMessage: 'Process' + }), + required: false, + presortedKeys: ['pid', 'title', 'args'] + }, + { + key: 'agent', + label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', { + defaultMessage: 'Agent' + }), + required: false, + presortedKeys: [] + }, + { + key: 'url', + label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', { + defaultMessage: 'URL' + }), + required: false, + presortedKeys: [] + }, + { + key: 'container', + label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', { + defaultMessage: 'Container' + }), + required: false, + presortedKeys: [] + }, + { + key: 'user', + label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', { + defaultMessage: 'User' + }), + required: true, + presortedKeys: ['id', 'username', 'email'] + }, + { + key: 'labels', + label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', { + defaultMessage: 'Labels' + }), + required: true, + presortedKeys: [] + }, + { + key: 'transaction.custom', + label: i18n.translate( + 'xpack.apm.propertiesTable.tabs.transactionCustomLabel', + { + defaultMessage: 'Custom' + } + ), + required: false, + presortedKeys: [] + }, + { + key: 'error.custom', + label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', { + defaultMessage: 'Custom' + }), + required: false, + presortedKeys: [] + } +]; diff --git a/x-pack/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js index b52a4020c59231..39e33c9613e445 100644 --- a/x-pack/plugins/canvas/.storybook/webpack.config.js +++ b/x-pack/plugins/canvas/.storybook/webpack.config.js @@ -17,7 +17,7 @@ module.exports = (_baseConfig, _env, config) => { include: /\.storybook/, loaders: 'babel-loader', options: { - presets: [require.resolve('babel-preset-react')], + presets: [require.resolve('@babel/preset-react')], }, }, ); diff --git a/x-pack/plugins/canvas/public/components/workpad_page/index.js b/x-pack/plugins/canvas/public/components/workpad_page/index.js index adc6bae7418a96..7a408de3358313 100644 --- a/x-pack/plugins/canvas/public/components/workpad_page/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_page/index.js @@ -41,6 +41,7 @@ const mapDispatchToProps = dispatch => { }; }; +// eslint-disable-next-line const getRootElementId = (lookup, id) => { if (!lookup.has(id)) { return null; diff --git a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js index 6e93f9eb5fb4b6..d62fbe21fa0f04 100644 --- a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js +++ b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js @@ -436,6 +436,7 @@ export const applyLocalTransforms = (shapes, transformIntents) => { return shapes.map(shapeApplyLocalTransforms(transformIntents)); }; +// eslint-disable-next-line const getUpstreamTransforms = (shapes, shape) => shape.parent ? getUpstreamTransforms(shapes, shapes.find(s => s.id === shape.parent)).concat([ diff --git a/x-pack/plugins/canvas/tasks/helpers/babelhook.js b/x-pack/plugins/canvas/tasks/helpers/babelhook.js index 4a48d09449b208..dea18db918fcd5 100644 --- a/x-pack/plugins/canvas/tasks/helpers/babelhook.js +++ b/x-pack/plugins/canvas/tasks/helpers/babelhook.js @@ -5,7 +5,7 @@ */ const { resolve } = require('path'); -const register = require('babel-register'); +const register = require('@babel/register'); const options = { babelrc: false, presets: [require.resolve('@kbn/babel-preset/node_preset')], diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js new file mode 100644 index 00000000000000..f9933cd60f1cad --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/auto_follow_pattern_list.test.js @@ -0,0 +1,321 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick, getRandomString, findTestSubject } from './test_helpers'; +import { AutoFollowPatternList } from '../../public/app/sections/home/auto_follow_pattern_list'; +import { getAutoFollowPatternClientMock } from '../../fixtures/auto_follow_pattern'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +describe('', () => { + let server; + let find; + let exists; + let component; + let getMetadataFromEuiTable; + let getUserActions; + let tableCellsValues; + let rows; + let updateHttpMockResponse; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + (updateHttpMockResponse = mockAllHttpRequests(server)); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists } = initTestBed(AutoFollowPatternList)); + }); + + test('should show a loading indicator on component', async () => { + expect(exists('ccrAutoFollowPatternLoading')).toBe(true); + }); + }); + + describe('when there are no auto-follow patterns', () => { + beforeEach(async () => { + ({ exists, component } = initTestBed(AutoFollowPatternList)); + + await nextTick(); // We need to wait next tick for the mock server response to comes in + component.update(); + }); + + test('should display an empty prompt', async () => { + expect(exists('ccrAutoFollowPatternEmptyPrompt')).toBe(true); + }); + + test('should have a button to create a follower index', async () => { + expect(exists('ccrCreateAutoFollowPatternButton')).toBe(true); + }); + }); + + describe('when there are auto-follow patterns', async () => { + // For deterministic tests, we need to make sure that autoFollowPattern1 comes before autoFollowPattern2 + // in the table list that is rendered. As the table orders alphabetically by index name + // we prefix the random name to make sure that autoFollowPattern1 comes before autoFollowPattern2 + const testPrefix = 'prefix_'; + const testSuffix = '_suffix'; + + const autoFollowPattern1 = getAutoFollowPatternClientMock({ + name: `a${getRandomString()}`, + followIndexPattern: `${testPrefix}{{leader_index}}${testSuffix}` + }); + const autoFollowPattern2 = getAutoFollowPatternClientMock({ + name: `b${getRandomString()}`, + followIndexPattern: '{{leader_index}}' // no prefix nor suffix + }); + const autoFollowPatterns = [autoFollowPattern1, autoFollowPattern2]; + + let selectAutoFollowPatternAt; + let clickBulkDeleteButton; + let clickConfirmModalDeleteAutoFollowPattern; + let clickRowActionButtonAt; + let clickAutoFollowPatternAt; + + beforeEach(async () => { + updateHttpMockResponse('loadAutoFollowPatterns', { patterns: autoFollowPatterns }); + + // Mount the component + ({ + find, + exists, + component, + getMetadataFromEuiTable, + getUserActions, + } = initTestBed(AutoFollowPatternList)); + + await nextTick(); // Make sure that the Http request is fulfilled + component.update(); + + ({ + selectAutoFollowPatternAt, + clickBulkDeleteButton, + clickConfirmModalDeleteAutoFollowPattern, + clickRowActionButtonAt, + clickAutoFollowPatternAt, + } = getUserActions('autoFollowPatternList')); + + // Read the index list table + ({ tableCellsValues, rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable')); + }); + + afterEach(async () => { + // The updates are not all synchronouse + // We need to wait for all the updates to ran before unmounting our component + await nextTick(100); + }); + + test('should not display the empty prompt', () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(false); + }); + + test('should have a button to create an auto-follow pattern', () => { + expect(exists('ccrCreateAutoFollowPatternButton')).toBe(true); + }); + + test('should list the auto-follow patterns in the table', () => { + expect(tableCellsValues.length).toEqual(autoFollowPatterns.length); + expect(tableCellsValues).toEqual([ + [ '', // Empty because the first column is the checkbox to select row + autoFollowPattern1.name, + autoFollowPattern1.remoteCluster, + autoFollowPattern1.leaderIndexPatterns.join(', '), + testPrefix, + testSuffix, + '' // Empty because the last column is for the "actions" on the resource + ], [ '', + autoFollowPattern2.name, + autoFollowPattern2.remoteCluster, + autoFollowPattern2.leaderIndexPatterns.join(', '), + '', // no prefix + '', // no suffix + '' ] + ]); + }); + + describe('bulk delete button', () => { + test('should be visible when an auto-follow pattern is selected', () => { + expect(exists('ccrAutoFollowPatternListBulkDeleteActionButton')).toBe(false); + + selectAutoFollowPatternAt(0); + + expect(exists('ccrAutoFollowPatternListBulkDeleteActionButton')).toBe(true); + }); + + test('should update the button label according to the number of patterns selected', () => { + selectAutoFollowPatternAt(0); // 1 auto-follow pattern selected + expect(find('ccrAutoFollowPatternListBulkDeleteActionButton').text()).toEqual('Delete auto-follow pattern'); + + selectAutoFollowPatternAt(1); // 2 auto-follow patterns selected + expect(find('ccrAutoFollowPatternListBulkDeleteActionButton').text()).toEqual('Delete auto-follow patterns'); + }); + + test('should open a confirmation modal when clicking the delete button', () => { + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + selectAutoFollowPatternAt(0); + clickBulkDeleteButton(); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + + test('should remove the auto-follow pattern from the table after delete is complete', async () => { + // Make sure that we have our 2 auto-follow patterns in the table + expect(rows.length).toBe(2); + + // We wil delete the *first* auto-follow pattern in the table + updateHttpMockResponse('deleteAutoFollowPattern', { itemsDeleted: [autoFollowPattern1.name] }); + + selectAutoFollowPatternAt(0); + clickBulkDeleteButton(); + clickConfirmModalDeleteAutoFollowPattern(); + + await nextTick(); + component.update(); + + ({ rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable')); + + expect(rows.length).toBe(1); + expect(rows[0].columns[1].value).toEqual(autoFollowPattern2.name); + }); + }); + + describe('table row actions', () => { + test('should have a "delete" and an "edit" action button on each row', () => { + const indexLastColumn = rows[0].columns.length - 1; + const tableCellActions = rows[0].columns[indexLastColumn].reactWrapper; + + const deleteButton = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListDeleteActionButton'); + const editButton = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListEditActionButton'); + + expect(deleteButton.length).toBe(1); + expect(editButton.length).toBe(1); + }); + + test('should open a confirmation modal when clicking on "delete" button', async () => { + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + clickRowActionButtonAt(0, 'delete'); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + }); + + describe('detail panel', () => { + test('should open a detail panel when clicking on a follower index', () => { + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(false); + + clickAutoFollowPatternAt(0); + + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(true); + }); + + test('should set the title the index that has been selected', () => { + clickAutoFollowPatternAt(0); // Open the detail panel + expect(find('autoFollowPatternDetailsFlyoutTitle').text()).toEqual(autoFollowPattern1.name); + }); + + test('should have a "settings" section', () => { + clickAutoFollowPatternAt(0); + expect(find('ccrAutoFollowPatternDetailPanelSettingsSection').find('h3').text()).toEqual('Settings'); + expect(exists('ccrAutoFollowPatternDetailPanelSettingsValues')).toBe(true); + }); + + test('should set the correct follower index settings values', () => { + clickAutoFollowPatternAt(0); + + expect(find('ccrAutoFollowPatternDetailRemoteCluster').text()).toEqual(autoFollowPattern1.remoteCluster); + expect(find('ccrAutoFollowPatternDetailLeaderIndexPatterns').text()).toEqual(autoFollowPattern1.leaderIndexPatterns.join(', ')); + expect(find('ccrAutoFollowPatternDetailPatternPrefix').text()).toEqual(testPrefix); + expect(find('ccrAutoFollowPatternDetailPatternSuffix').text()).toEqual(testSuffix); + }); + + test('should have a default value when there are no prefix or no suffix', () => { + clickAutoFollowPatternAt(1); // Does not have prefix and suffix + + expect(find('ccrAutoFollowPatternDetailPatternPrefix').text()).toEqual('No prefix'); + expect(find('ccrAutoFollowPatternDetailPatternSuffix').text()).toEqual('No suffix'); + }); + + test('should show a preview of the indices that might be generated by the auto-follow pattern', () => { + clickAutoFollowPatternAt(0); + const detailPanel = find('ccrAutoFollowPatternDetailsFlyout'); + const indicesPreview = findTestSubject(detailPanel, 'ccrAutoFollowPatternIndexPreview'); + + expect(exists('ccrAutoFollowPatternDetailPanelIndicesPreviewSection')).toBe(true); + expect(indicesPreview.length).toBe(3); + }); + + test('should have a link to view the indices in Index Management', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailsViewIndexManagementButton')).toBe(true); + expect(find('ccrAutoFollowPatternDetailsViewIndexManagementButton').text()).toBe('View your follower indices in Index Management'); + }); + + test('should have a "close", "delete" and "edit" button in the footer', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailsFlyoutCloseButton')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsDeleteActionButton')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsEditActionButton')).toBe(true); + }); + + test('should close the detail panel when clicking the "close" button', () => { + clickAutoFollowPatternAt(0); // open the detail panel + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(true); + + find('ccrAutoFollowPatternDetailsFlyoutCloseButton').simulate('click'); // close the detail panel + + expect(exists('ccrAutoFollowPatternDetailsFlyout')).toBe(false); + }); + + test('should open a confirmation modal when clicking the "delete" button', () => { + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(false); + + find('ccrAutoFollowPatternDetailsDeleteActionButton').simulate('click'); + + expect(exists('ccrAutoFollowPatternDeleteConfirmationModal')).toBe(true); + }); + + test('should display the recent errors', async () => { + const message = 'bar'; + const recentAutoFollowErrors = [{ + leaderIndex: `${autoFollowPattern1.name}:my-leader-test`, + autoFollowException: { type: 'exception', reason: message } + }, { + leaderIndex: `${autoFollowPattern2.name}:my-leader-test`, + autoFollowException: { type: 'exception', reason: message } + }]; + updateHttpMockResponse('autoFollowStats', { recentAutoFollowErrors }); + + clickAutoFollowPatternAt(0); + expect(exists('ccrAutoFollowPatternDetailErrors')).toBe(false); + + // We select the other auto-follow pattern because the stats are fetched + // each time we change the auto-follow pattern selection + clickAutoFollowPatternAt(1); + await nextTick(); + component.update(); + + expect(exists('ccrAutoFollowPatternDetailErrors')).toBe(true); + expect(exists('ccrAutoFollowPatternDetailsTitleErrors')).toBe(true); + expect(find('ccrAutoFollowPatternDetailRecentError').map(error => error.text())).toEqual([message]); + }); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js new file mode 100644 index 00000000000000..eb30e796cbaead --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/follower_indices_list.test.js @@ -0,0 +1,343 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick, getRandomString } from './test_helpers'; +import { FollowerIndicesList } from '../../public/app/sections/home/follower_indices_list'; +import { getFollowerIndexMock } from '../../fixtures/follower_index'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +describe('', () => { + let server; + let find; + let exists; + let component; + let getMetadataFromEuiTable; + let getUserActions; + let tableCellsValues; + let updateHttpMockResponse; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + (updateHttpMockResponse = mockAllHttpRequests(server)); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists } = initTestBed(FollowerIndicesList)); + }); + + test('should show a loading indicator on component', async () => { + expect(exists('ccrFollowerIndexLoading')).toBe(true); + }); + }); + + describe('when there are no follower indices', () => { + beforeEach(async () => { + ({ exists, component } = initTestBed(FollowerIndicesList)); + + await nextTick(); // We need to wait next tick for the mock server response to comes in + component.update(); + }); + + test('should display an empty prompt', async () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(true); + }); + + test('should have a button to create a follower index', async () => { + expect(exists('ccrFollowerIndexEmptyPromptCreateButton')).toBe(true); + }); + }); + + describe('when there are follower indices', async () => { + // For deterministic tests, we need to make sure that index1 comes before index2 + // in the table list that is rendered. As the table orders alphabetically by index name + // we prefix the random name to make sure that index1 name comes before index2. + const index1 = getFollowerIndexMock({ name: `a${getRandomString()}` }); + const index2 = getFollowerIndexMock({ name: `b${getRandomString()}`, status: 'paused' }); + + const followerIndices = [index1, index2]; + + let selectFollowerIndexAt; + let openContextMenu; + let openTableRowContextMenuAt; + let clickContextMenuButtonAt; + let clickFollowerIndexAt; + + beforeEach(async () => { + updateHttpMockResponse('loadFollowerIndices', { indices: followerIndices }); + + // Mount the component + ({ + find, + exists, + component, + getMetadataFromEuiTable, + getUserActions, + } = initTestBed(FollowerIndicesList)); + + await nextTick(); // Make sure that the Http request is fulfilled + component.update(); + + ({ + selectFollowerIndexAt, + openContextMenu, + openTableRowContextMenuAt, + clickContextMenuButtonAt, + clickFollowerIndexAt, + } = getUserActions('followerIndicesList')); + + // Read the index list table + ({ tableCellsValues } = getMetadataFromEuiTable('ccrFollowerIndexListTable')); + }); + + afterEach(async () => { + // The updates are not all synchronouse + // We need to wait for all the updates to ran before unmounting our component + await nextTick(100); + }); + + test('should not display the empty prompt', () => { + expect(exists('ccrFollowerIndexEmptyPrompt')).toBe(false); + }); + + test('should have a button to create a follower index', () => { + expect(exists('ccrCreateFollowerIndexButton')).toBe(true); + }); + + test('should list the follower indices in the table', () => { + expect(tableCellsValues.length).toEqual(followerIndices.length); + expect(tableCellsValues).toEqual([ + [ '', // Empty because the first column is the checkbox to select row + index1.name, + 'Active', + index1.remoteCluster, + index1.leaderIndex, + '' // Empty because the last column is for the "actions" on the resource + ], [ '', + index2.name, + 'Paused', + index2.remoteCluster, + index2.leaderIndex, + '' ] + ]); + }); + + describe('action menu', () => { + test('should be visible when a follower index is selected', () => { + expect(exists('ccrFollowerIndexListContextMenuButton')).toBe(false); + + selectFollowerIndexAt(0); + + expect(exists('ccrFollowerIndexListContextMenuButton')).toBe(true); + }); + + test('should have a "pause", "edit" and "unfollow" action when the follower index is active', async () => { + selectFollowerIndexAt(0); + openContextMenu(); + + const contextMenu = find('followerIndexActionContextMenu'); + + expect(contextMenu.length).toBeTruthy(); + const contextMenuButtons = contextMenu.find('button'); + const buttonsLabel = contextMenuButtons.map(btn => btn.text()); + + expect(buttonsLabel).toEqual([ + 'Pause replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should have a "resume", "edit" and "unfollow" action when the follower index is active', async () => { + selectFollowerIndexAt(1); // Select the second follower that is "paused" + openContextMenu(); + + const contextMenu = find('followerIndexActionContextMenu'); + + const contextMenuButtons = contextMenu.find('button'); + const buttonsLabel = contextMenuButtons.map(btn => btn.text()); + expect(buttonsLabel).toEqual([ + 'Resume replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should open a confirmation modal when clicking on "pause replication"', () => { + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(false); + + selectFollowerIndexAt(0); + openContextMenu(); + clickContextMenuButtonAt(0); // first button is the "pause" action + + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "unfollow leader index"', () => { + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(false); + + selectFollowerIndexAt(0); + openContextMenu(); + clickContextMenuButtonAt(2); // third button is the "unfollow" action + + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(true); + }); + }); + + describe('table row action menu', () => { + test('should open a context menu when clicking on the button of each row', async () => { + expect(component.find('.euiContextMenuPanel').length).toBe(0); + + openTableRowContextMenuAt(0); + + expect(component.find('.euiContextMenuPanel').length).toBe(1); + }); + + test('should have the "pause", "edit" and "unfollow" options in the row context menu', async () => { + openTableRowContextMenuAt(0); + + const buttonLabels = component + .find('.euiContextMenuPanel') + .find('.euiContextMenuItem') + .map(button => button.text()); + + expect(buttonLabels).toEqual([ + 'Pause replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should have the "resume", "edit" and "unfollow" options in the row context menu', async () => { + // We open the context menu of the second row (index 1) as followerIndices[1].status is "paused" + openTableRowContextMenuAt(1); + + const buttonLabels = component + .find('.euiContextMenuPanel') + .find('.euiContextMenuItem') + .map(button => button.text()); + + expect(buttonLabels).toEqual([ + 'Resume replication', + 'Edit follower index', + 'Unfollow leader index' + ]); + }); + + test('should open a confirmation modal when clicking on "pause replication"', async () => { + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(0); + find('ccrFollowerIndexListPauseActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexPauseReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "resume"', async () => { + expect(exists('ccrFollowerIndexResumeReplicationConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(1); // open the second row context menu, as it is a "paused" follower index + find('ccrFollowerIndexListResumeActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexResumeReplicationConfirmationModal')).toBe(true); + }); + + test('should open a confirmation modal when clicking on "unfollow leader index"', () => { + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(false); + + openTableRowContextMenuAt(0); + find('ccrFollowerIndexListUnfollowActionButton').simulate('click'); + + expect(exists('ccrFollowerIndexUnfollowLeaderConfirmationModal')).toBe(true); + }); + }); + + describe('detail panel', () => { + test('should open a detail panel when clicking on a follower index', () => { + expect(exists('ccrFollowerIndexDetailsFlyout')).toBe(false); + + clickFollowerIndexAt(0); + + expect(exists('ccrFollowerIndexDetailsFlyout')).toBe(true); + }); + + test('should set the title the index that has been selected', () => { + clickFollowerIndexAt(0); // Open the detail panel + expect(find('followerIndexDetailsFlyoutTitle').text()).toEqual(index1.name); + }); + + test('should have a "settings" section', () => { + clickFollowerIndexAt(0); + expect(find('ccrFollowerIndexDetailPanelSettingsSection').find('h3').text()).toEqual('Settings'); + expect(exists('ccrFollowerIndexDetailPanelSettingsValues')).toBe(true); + }); + + test('should set the correct follower index settings values', () => { + const mapSettingsToFollowerIndexProp = { + 'Status': 'status', + 'RemoteCluster': 'remoteCluster', + 'LeaderIndex': 'leaderIndex', + 'MaxReadReqOpCount': 'maxReadRequestOperationCount', + 'MaxOutstandingReadReq': 'maxOutstandingReadRequests', + 'MaxReadReqSize': 'maxReadRequestSize', + 'MaxWriteReqOpCount': 'maxWriteRequestOperationCount', + 'MaxWriteReqSize': 'maxWriteRequestSize', + 'MaxOutstandingWriteReq': 'maxOutstandingWriteRequests', + 'MaxWriteBufferCount': 'maxWriteBufferCount', + 'MaxWriteBufferSize': 'maxWriteBufferSize', + 'MaxRetryDelay': 'maxRetryDelay', + 'ReadPollTimeout': 'readPollTimeout' + }; + + clickFollowerIndexAt(0); + + Object.entries(mapSettingsToFollowerIndexProp).forEach(([setting, prop]) => { + const wrapper = find(`ccrFollowerIndexDetail${setting}`); + + if (!wrapper.length) { + throw new Error(`Could not find description for setting "${setting}"`); + } + + expect(wrapper.text()).toEqual(index1[prop].toString()); + }); + }); + + test('should not have settings values for a "paused" follower index', () => { + clickFollowerIndexAt(1); // the second follower index is paused + expect(exists('ccrFollowerIndexDetailPanelSettingsValues')).toBe(false); + expect(find('ccrFollowerIndexDetailPanelSettingsSection').text()).toContain('paused follower index does not have settings'); + }); + + test('should have a section to render the follower index shards stats', () => { + clickFollowerIndexAt(0); + expect(exists('ccrFollowerIndexDetailPanelShardsStatsSection')).toBe(true); + }); + + test('should render a EuiCodeEditor for each shards stats', () => { + clickFollowerIndexAt(0); + + const codeEditors = component.find(`EuiCodeEditor`); + + expect(codeEditors.length).toBe(index1.shards.length); + codeEditors.forEach((codeEditor, i) => { + expect(JSON.parse(codeEditor.props().value)).toEqual(index1.shards[i]); + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js new file mode 100644 index 00000000000000..5d09018a2bbd61 --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/home.test.js @@ -0,0 +1,84 @@ +/* + * 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 sinon from 'sinon'; + +import { initTestBed, mockAllHttpRequests, nextTick } from './test_helpers'; +import { CrossClusterReplicationHome } from '../../public/app/sections/home/home'; +import { BASE_PATH } from '../../common/constants'; +import routing from '../../public/app/services/routing'; + +jest.mock('ui/chrome', () => ({ + addBasePath: () => 'api/cross_cluster_replication', + breadcrumbs: { set: () => {} }, +})); + +jest.mock('ui/index_patterns', () => { + const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } = require.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants'); // eslint-disable-line max-len + return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE }; +}); + +const testBedOptions = { + memoryRouter: { + initialEntries: [`${BASE_PATH}/follower_indices`], + componentRoutePath: `${BASE_PATH}/:section`, + onRouter: (router) => routing.reactRouter = router + } +}; + +describe('', () => { + let server; + let find; + let exists; + let component; + + beforeEach(() => { + server = sinon.fakeServer.create(); + server.respondImmediately = true; + mockAllHttpRequests(server); + }); + + describe('on component mount', () => { + beforeEach(async () => { + ({ exists, find, component } = initTestBed(CrossClusterReplicationHome, undefined, testBedOptions)); + }); + + test('should set the correct an app title', () => { + expect(exists('ccrAppTitle')).toBe(true); + expect(find('ccrAppTitle').text()).toEqual('Cross Cluster Replication'); + }); + + test('should have 2 tabs to switch between "Follower indices" & "Auto-follow patterns"', () => { + expect(exists('ccrFollowerIndicesTab')).toBe(true); + expect(find('ccrFollowerIndicesTab').text()).toEqual('Follower indices'); + + expect(exists('ccrAutoFollowPatternsTab')).toBe(true); + expect(find('ccrAutoFollowPatternsTab').text()).toEqual('Auto-follow patterns'); + }); + + test('should set the default selected tab to "Follower indices"', () => { + expect(component.find('.euiTab-isSelected').text()).toBe('Follower indices'); + + // Verify that the component is rendered + expect(component.find('FollowerIndicesList').length).toBe(1); + }); + }); + + describe('section change', () => { + test('should change to auto-follow pattern', async () => { + const autoFollowPatternsTab = find('ccrAutoFollowPatternsTab'); + + autoFollowPatternsTab.simulate('click'); + await nextTick(); + component.update(); + + expect(component.find('.euiTab-isSelected').text()).toBe('Auto-follow patterns'); + + // Verify that the component is rendered + expect(component.find('AutoFollowPatternList').length).toBe(1); + }); + }); +}); diff --git a/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js new file mode 100644 index 00000000000000..2bd747977c1114 --- /dev/null +++ b/x-pack/plugins/cross_cluster_replication/__jest__/client_integration/test_helpers.js @@ -0,0 +1,212 @@ +/* + * 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 axios from 'axios'; + +import { registerTestBed, findTestSubject } from '../../../../test_utils'; +import { ccrStore } from '../../public/app/store'; +import { setHttpClient } from '../../public/app/services/api'; +import routing from '../../public/app/services/routing'; + +// Mock React router +const reactRouter = { + history: { + push: () => {}, + createHref: (location) => location.pathname, + location: '' + } +}; + +routing.reactRouter = reactRouter; +// Mock Angular $q +const $q = { defer: () => ({ resolve() {} }) }; +// axios has a $http like interface so using it to simulate $http +setHttpClient(axios.create(), $q); + +const initUserActions = ({ getMetadataFromEuiTable, find }) => (section) => { + const userActions = { + // Follower indices user actions + followerIndicesList() { + const { rows } = getMetadataFromEuiTable('ccrFollowerIndexListTable'); + + const selectFollowerIndexAt = (index = 0) => { + const row = rows[index]; + const checkBox = row.reactWrapper.find('input').hostNodes(); + checkBox.simulate('change', { target: { checked: true } }); + }; + + const openContextMenu = () => { + find('ccrFollowerIndexListContextMenuButton').simulate('click'); + }; + + const clickContextMenuButtonAt = (index = 0) => { + const contextMenu = find('followerIndexActionContextMenu'); + contextMenu.find('button').at(index).simulate('click'); + }; + + const openTableRowContextMenuAt = (index = 0) => { + const actionsColumnIndex = rows[0].columns.length - 1; // Actions are in the last column + const actionsTableCell = rows[index].columns[actionsColumnIndex]; + const button = actionsTableCell.reactWrapper.find('button'); + if (!button.length) { + throw new Error(`No button to open context menu were found on Follower index list table row ${index}`); + } + button.simulate('click'); + }; + + const clickFollowerIndexAt = (index = 0) => { + const followerIndexLink = findTestSubject(rows[index].reactWrapper, 'ccrFollowerIndexListFollowerIndexLink'); + followerIndexLink.simulate('click'); + }; + + return { + selectFollowerIndexAt, + openContextMenu, + clickContextMenuButtonAt, + openTableRowContextMenuAt, + clickFollowerIndexAt, + }; + }, + // Auto-follow patterns user actions + autoFollowPatternList() { + const { rows } = getMetadataFromEuiTable('ccrAutoFollowPatternListTable'); + + const selectAutoFollowPatternAt = (index = 0) => { + const row = rows[index]; + const checkBox = row.reactWrapper.find('input').hostNodes(); + checkBox.simulate('change', { target: { checked: true } }); + }; + + const clickBulkDeleteButton = () => { + find('ccrAutoFollowPatternListBulkDeleteActionButton').simulate('click'); + }; + + const clickConfirmModalDeleteAutoFollowPattern = () => { + const modal = find('ccrAutoFollowPatternDeleteConfirmationModal'); + findTestSubject(modal, 'confirmModalConfirmButton').simulate('click'); + }; + + const clickRowActionButtonAt = (index = 0, action = 'delete') => { + const indexLastColumn = rows[index].columns.length - 1; + const tableCellActions = rows[index].columns[indexLastColumn].reactWrapper; + + let button; + if (action === 'delete') { + button = findTestSubject(tableCellActions, 'ccrAutoFollowPatternListDeleteActionButton'); + } else if (action === 'edit') { + findTestSubject(tableCellActions, 'ccrAutoFollowPatternListEditActionButton'); + } + + if (!button) { + throw new Error(`Button for action "${action}" not found.`); + } + + button.simulate('click'); + }; + + const clickAutoFollowPatternAt = (index = 0) => { + const autoFollowPatternLink = findTestSubject(rows[index].reactWrapper, 'ccrAutoFollowPatternListPatternLink'); + autoFollowPatternLink.simulate('click'); + }; + + return { + selectAutoFollowPatternAt, + clickBulkDeleteButton, + clickConfirmModalDeleteAutoFollowPattern, + clickRowActionButtonAt, + clickAutoFollowPatternAt + }; + } + }; + + return userActions[section](); +}; + +export { nextTick, getRandomString, findTestSubject } from '../../../../test_utils'; + +export const initTestBed = (component, props = {}, options) => { + const testBed = registerTestBed(component, {}, ccrStore)(props, options); + const getUserActions = initUserActions(testBed); + + return { + ...testBed, + getUserActions, + }; +}; + +export const mockAllHttpRequests = server => { + const mockResponse = (defaultResponse, response) => ([ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ ...defaultResponse, ...response }), + ]); + + const setLoadFollowerIndicesResponse = (response) => { + const defaultResponse = { indices: [] }; + + server.respondWith('GET', 'api/cross_cluster_replication/follower_indices', + mockResponse(defaultResponse, response)); + }; + + const setLoadAutoFollowPatternsResponse = (response) => { + const defaultResponse = { patterns: [] }; + + server.respondWith('GET', 'api/cross_cluster_replication/auto_follow_patterns', + mockResponse(defaultResponse, response) + ); + }; + + const setDeleteAutoFollowPatternResponse = (response) => { + const defaultResponse = { errors: [], itemsDeleted: [] }; + + server.respondWith('DELETE', /api\/cross_cluster_replication\/auto_follow_patterns/, + mockResponse(defaultResponse, response) + ); + }; + + const setAutoFollowStatsResponse = (response) => { + const defaultResponse = { + numberOfFailedFollowIndices: 0, + numberOfFailedRemoteClusterStateRequests: 0, + numberOfSuccessfulFollowIndices: 0, + recentAutoFollowErrors: [], + autoFollowedClusters: [{ + clusterName: 'new-york', + timeSinceLastCheckMillis: 13746, + lastSeenMetadataVersion: 22 + }] + }; + + server.respondWith('GET', 'api/cross_cluster_replication/stats/auto_follow', + mockResponse(defaultResponse, response) + ); + }; + + /** + * Set all http request to their default response + */ + setLoadFollowerIndicesResponse(); + setLoadAutoFollowPatternsResponse(); + setAutoFollowStatsResponse(); + + /** + * Return a method to override any of the http reques + */ + return (request, response) => { + const mapRequestToHelper = { + 'loadFollowerIndices': setLoadFollowerIndicesResponse, + 'loadAutoFollowPatterns': setLoadAutoFollowPatternsResponse, + 'deleteAutoFollowPattern': setDeleteAutoFollowPatternResponse, + 'autoFollowStats': setAutoFollowStatsResponse, + }; + + if (!mapRequestToHelper[request]) { + throw new Error(`Did not find a helper to set http response for request ${request}`); + } + + return mapRequestToHelper[request](response); + }; +}; diff --git a/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js b/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js index 187b91b66ea73d..cfedad5c1c0727 100644 --- a/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js +++ b/x-pack/plugins/cross_cluster_replication/fixtures/auto_follow_pattern.js @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies -const chance = new Chance(); +import { getRandomString } from '../../../test_utils'; export const getAutoFollowPatternMock = ( - name = chance.string(), - remoteCluster = chance.string(), - leaderIndexPatterns = [chance.string()], - followIndexPattern = chance.string() + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndexPatterns = [getRandomString()], + followIndexPattern = getRandomString() ) => ({ name, pattern: { @@ -33,3 +32,18 @@ export const getAutoFollowPatternListMock = (total = 3) => { return list; }; + +// ----------------- +// Client test mock +// ----------------- +export const getAutoFollowPatternClientMock = ({ + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndexPatterns = [`${getRandomString()}-*`], + followIndexPattern = getRandomString() +}) => ({ + name, + remoteCluster, + leaderIndexPatterns, + followIndexPattern, +}); diff --git a/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js b/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js index ef888f8929a267..e873c1a394f44a 100644 --- a/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js +++ b/x-pack/plugins/cross_cluster_replication/fixtures/follower_index.js @@ -6,6 +6,63 @@ const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies const chance = new Chance(); +import { getRandomString } from '../../../test_utils'; + +const serializeShard = ({ + id, + remoteCluster, + leaderIndex, + leaderGlobalCheckpoint, + leaderMaxSequenceNum, + followerGlobalCheckpoint, + followerMaxSequenceNum, + lastRequestedSequenceNum, + outstandingReadRequestsCount, + outstandingWriteRequestsCount, + writeBufferOperationsCount, + writeBufferSizeBytes, + followerMappingVersion, + followerSettingsVersion, + totalReadTimeMs, + totalReadRemoteExecTimeMs, + successfulReadRequestCount, + failedReadRequestsCount, + operationsReadCount, + bytesReadCount, + totalWriteTimeMs, + successfulWriteRequestsCount, + failedWriteRequestsCount, + operationsWrittenCount, + readExceptions, + timeSinceLastReadMs, +}) => ({ + shard_id: id, + remote_cluster: remoteCluster, + leader_index: leaderIndex, + leader_global_checkpoint: leaderGlobalCheckpoint, + leader_max_seq_no: leaderMaxSequenceNum, + follower_global_checkpoint: followerGlobalCheckpoint, + follower_max_seq_no: followerMaxSequenceNum, + last_requested_seq_no: lastRequestedSequenceNum, + outstanding_read_requests: outstandingReadRequestsCount, + outstanding_write_requests: outstandingWriteRequestsCount, + write_buffer_operation_count: writeBufferOperationsCount, + write_buffer_size_in_bytes: writeBufferSizeBytes, + follower_mapping_version: followerMappingVersion, + follower_settings_version: followerSettingsVersion, + total_read_time_millis: totalReadTimeMs, + total_read_remote_exec_time_millis: totalReadRemoteExecTimeMs, + successful_read_requests: successfulReadRequestCount, + failed_read_requests: failedReadRequestsCount, + operations_read: operationsReadCount, + bytes_read: bytesReadCount, + total_write_time_millis: totalWriteTimeMs, + successful_write_requests: successfulWriteRequestsCount, + failed_write_requests: failedWriteRequestsCount, + operations_written: operationsWrittenCount, + read_exceptions: readExceptions, + time_since_last_read_millis: timeSinceLastReadMs, +}); export const getFollowerIndexStatsMock = ( name = chance.string(), @@ -37,68 +94,10 @@ export const getFollowerIndexStatsMock = ( readExceptions: [ chance.string() ], timeSinceLastReadMs: chance.integer(), }] -) => { - const serializeShard = ({ - id, - remoteCluster, - leaderIndex, - leaderGlobalCheckpoint, - leaderMaxSequenceNum, - followerGlobalCheckpoint, - followerMaxSequenceNum, - lastRequestedSequenceNum, - outstandingReadRequestsCount, - outstandingWriteRequestsCount, - writeBufferOperationsCount, - writeBufferSizeBytes, - followerMappingVersion, - followerSettingsVersion, - totalReadTimeMs, - totalReadRemoteExecTimeMs, - successfulReadRequestCount, - failedReadRequestsCount, - operationsReadCount, - bytesReadCount, - totalWriteTimeMs, - successfulWriteRequestsCount, - failedWriteRequestsCount, - operationsWrittenCount, - readExceptions, - timeSinceLastReadMs, - }) => ({ - shard_id: id, - remote_cluster: remoteCluster, - leader_index: leaderIndex, - leader_global_checkpoint: leaderGlobalCheckpoint, - leader_max_seq_no: leaderMaxSequenceNum, - follower_global_checkpoint: followerGlobalCheckpoint, - follower_max_seq_no: followerMaxSequenceNum, - last_requested_seq_no: lastRequestedSequenceNum, - outstanding_read_requests: outstandingReadRequestsCount, - outstanding_write_requests: outstandingWriteRequestsCount, - write_buffer_operation_count: writeBufferOperationsCount, - write_buffer_size_in_bytes: writeBufferSizeBytes, - follower_mapping_version: followerMappingVersion, - follower_settings_version: followerSettingsVersion, - total_read_time_millis: totalReadTimeMs, - total_read_remote_exec_time_millis: totalReadRemoteExecTimeMs, - successful_read_requests: successfulReadRequestCount, - failed_read_requests: failedReadRequestsCount, - operations_read: operationsReadCount, - bytes_read: bytesReadCount, - total_write_time_millis: totalWriteTimeMs, - successful_write_requests: successfulWriteRequestsCount, - failed_write_requests: failedWriteRequestsCount, - operations_written: operationsWrittenCount, - read_exceptions: readExceptions, - time_since_last_read_millis: timeSinceLastReadMs, - }); - - return { - index: name, - shards: shards.map(serializeShard), - }; -}; +) => ({ + index: name, + shards: shards.map(serializeShard), +}); export const getFollowerIndexListStatsMock = (total = 3, names) => { const list = { @@ -157,3 +156,57 @@ export const getFollowerIndexListInfoMock = (total = 3) => { return list; }; + +// ----------------- +// Client test mock +// ----------------- + +export const getFollowerIndexMock = ({ + name = getRandomString(), + remoteCluster = getRandomString(), + leaderIndex = getRandomString(), + status = 'Active' +} = {}) => ({ + name, + remoteCluster, + leaderIndex, + status, + maxReadRequestOperationCount: chance.integer(), + maxOutstandingReadRequests: chance.integer(), + maxReadRequestSize: getRandomString({ length: 5 }), + maxWriteRequestOperationCount: chance.integer(), + maxWriteRequestSize: '9223372036854775807b', + maxOutstandingWriteRequests: chance.integer(), + maxWriteBufferCount: chance.integer(), + maxWriteBufferSize: getRandomString({ length: 5 }), + maxRetryDelay: getRandomString({ length: 5 }), + readPollTimeout: getRandomString({ length: 5 }), + shards: [{ + id: 0, + remoteCluster: remoteCluster, + leaderIndex: leaderIndex, + leaderGlobalCheckpoint: chance.integer(), + leaderMaxSequenceNum: chance.integer(), + followerGlobalCheckpoint: chance.integer(), + followerMaxSequenceNum: chance.integer(), + lastRequestedSequenceNum: chance.integer(), + outstandingReadRequestsCount: chance.integer(), + outstandingWriteRequestsCount: chance.integer(), + writeBufferOperationsCount: chance.integer(), + writeBufferSizeBytes: chance.integer(), + followerMappingVersion: chance.integer(), + followerSettingsVersion: chance.integer(), + totalReadTimeMs: chance.integer(), + totalReadRemoteExecTimeMs: chance.integer(), + successfulReadRequestCount: chance.integer(), + failedReadRequestsCount: chance.integer(), + operationsReadCount: chance.integer(), + bytesReadCount: chance.integer(), + totalWriteTimeMs: chance.integer(), + successfulWriteRequestsCount: chance.integer(), + failedWriteRequestsCount: chance.integer(), + operationsWrittenCount: chance.integer(), + readExceptions: [], + timeSinceLastReadMs: chance.integer(), + }] +}); diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js index e48347a1711275..9c617446b28a25 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_delete_provider.js @@ -87,6 +87,7 @@ class AutoFollowPatternDeleteProviderUi extends PureComponent { ) } onMouseOver={this.onMouseOverModal} + data-test-subj="ccrAutoFollowPatternDeleteConfirmationModal" > {!isSingle && ( diff --git a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js index 3e41cb9bdcefd6..c76c13c44d51fa 100644 --- a/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js +++ b/x-pack/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_indices_preview.js @@ -36,7 +36,7 @@ export const AutoFollowPatternIndicesPreview = ({ prefix, suffix, leaderIndexPat />