diff --git a/.eslintrc.js b/.eslintrc.js index f1e0b7d9353e8b..aeaf6e04fdc01d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -50,7 +50,7 @@ const ELASTIC_LICENSE_HEADER = ` `; const allMochaRulesOff = {}; -Object.keys(require('eslint-plugin-mocha').rules).forEach(k => { +Object.keys(require('eslint-plugin-mocha').rules).forEach((k) => { allMochaRulesOff['mocha/' + k] = 'off'; }); @@ -133,7 +133,7 @@ module.exports = { * Licence headers */ { - files: ['**/*.{js,ts,tsx}'], + files: ['**/*.{js,ts,tsx}', '!plugins/**/*'], rules: { '@kbn/eslint/require-license-header': [ 'error', @@ -197,6 +197,11 @@ module.exports = { from: ['src/core/utils/**/*'], errorMessage: `Plugins may only import from src/core/server and src/core/public.`, }, + { + target: ['(src|x-pack)/plugins/*/public/**/*'], + from: ['(src|x-pack)/plugins/*/server/**/*'], + errorMessage: `Public code can not import from server, use a common directory.`, + }, { target: [ '(src|x-pack)/legacy/**/*', @@ -219,6 +224,8 @@ module.exports = { // for absolute imports until fixed in // https://github.com/elastic/kibana/issues/36096 '!src/core/server/*.test.mocks{,.ts}', + + 'target/types/**', ], allowSameFolder: true, errorMessage: @@ -491,7 +498,6 @@ module.exports = { '.eslintrc.js', '**/webpackShims/**/*.js', 'packages/kbn-plugin-generator/**/*.js', - 'packages/kbn-plugin-helpers/**/*.js', 'packages/kbn-eslint-import-resolver-kibana/**/*.js', 'packages/kbn-eslint-plugin-eslint/**/*', 'x-pack/gulpfile.js', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19116977756f48..a160094a541300 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,6 +78,7 @@ # Canvas /x-pack/plugins/canvas/ @elastic/kibana-canvas +/x-pack/test/functional/apps/canvas/ @elastic/kibana-canvas # Observability UIs /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui @@ -127,9 +128,14 @@ /src/legacy/server/sass/ @elastic/kibana-operations /src/legacy/server/utils/ @elastic/kibana-operations /src/legacy/server/warnings/ @elastic/kibana-operations +/.ci/es-snapshots/ @elastic/kibana-operations +/vars/ @elastic/kibana-operations # Quality Assurance /src/dev/code_coverage @elastic/kibana-qa +/test/functional/services/common @elastic/kibana-qa +/test/functional/services/lib @elastic/kibana-qa +/test/functional/services/remote @elastic/kibana-qa # Platform /src/core/ @elastic/kibana-platform diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index d9d99fc1416e46..039b520561d65b 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -10,6 +10,9 @@ - "src/plugins/bfetch/**/*.*" - "Team:apm": - "x-pack/plugins/apm/**/*.*" - - "x-pack/plugins/apm/**/*.*" + - "Team:Ingest Management": + - "x-pack/plugins/ingest_manager/**/*.*" + - "x-pack/test/api_integration/apis/fleet/**/*.*" + - "x-pack/test/epm_api_integration/**/*.*" - "Team:uptime": - "x-pack/plugins/uptime/**/*.*" diff --git a/.i18nrc.json b/.i18nrc.json index 034b9da799d3ec..9af7f17067b8e3 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -56,7 +56,8 @@ "visTypeVislib": "src/plugins/vis_type_vislib", "visTypeXy": "src/plugins/vis_type_xy", "visualizations": "src/plugins/visualizations", - "visualize": "src/plugins/visualize" + "visualize": "src/plugins/visualize", + "apmOss": "src/plugins/apm_oss" }, "exclude": [ "src/legacy/ui/ui_render/ui_render_mixin.js" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9a2f609e0913f..1053cc2f653961 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -490,6 +490,14 @@ module.exports = { }; ``` +APM [Real User Monitoring agent](https://www.elastic.co/guide/en/apm/agent/rum-js/current/index.html) is not available in the Kibana distributables, +however the agent can be enabled by setting `ELASTIC_APM_ACTIVE` to `true`. +flags +``` +ELASTIC_APM_ACTIVE=true yarn start +// activates both Node.js and RUM agent +``` + Once the agent is active, it will trace all incoming HTTP requests to Kibana, monitor for errors, and collect process-level metrics. The collected data will be sent to the APM Server and is viewable in the APM UI in Kibana. diff --git a/Gruntfile.js b/Gruntfile.js index c33a576d4340fa..0216ab12f7cc53 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -19,7 +19,7 @@ require('./src/setup_node_env'); -module.exports = function(grunt) { +module.exports = function (grunt) { // set the config once before calling load-grunt-config // and once during so that we have access to it via // grunt.config.get() within the config files diff --git a/Jenkinsfile b/Jenkinsfile index 958ced8c6195a6..f435b18c6d824e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,7 +3,7 @@ library 'kibana-pipeline-library' kibanaLibrary.load() -kibanaPipeline(timeoutMinutes: 135, checkPrChanges: true) { +kibanaPipeline(timeoutMinutes: 155, checkPrChanges: true) { ciStats.trackBuild { githubPr.withDefaultPrComments { catchError { @@ -53,7 +53,9 @@ kibanaPipeline(timeoutMinutes: 135, checkPrChanges: true) { } } - retryable.printFlakyFailures() - kibanaPipeline.sendMail() + if (params.NOTIFY_ON_FAILURE) { + slackNotifications.onFailure() + kibanaPipeline.sendMail() + } } } diff --git a/docs/apm/api.asciidoc b/docs/apm/api.asciidoc index b26c7446b91d11..3e4b515e009de1 100644 --- a/docs/apm/api.asciidoc +++ b/docs/apm/api.asciidoc @@ -9,14 +9,45 @@ Some APM app features are provided via a REST API: * <> - -TIP: Kibana provides additional <>, -and general information on <>. +* <> + +Here's an example CURL request that adds an annotation to the APM app: + +[source,curl] +---- +curl -X POST \ + http://localhost:5601/api/apm/services/opbeans-java/annotation \ +-H 'Content-Type: application/json' \ +-H 'kbn-xsrf: true' \ +-H 'Authorization: Basic YhUlubWZhM0FDbnlQeE6WRtaW49FQmSGZ4RUWXdX' \ +-d '{ + "@timestamp": "2020-05-11T10:31:30.452Z", + "service": { + "version": "1.2" + }, + "message": "Revert upgrade", + "tags": [ + "elastic.co", "customer" + ] + }' +---- + +For more information, the Kibana <> provides information on how to use Kibana APIs, +like required request headers and authentication options. + +// AGENT CONFIG API +// GET --> Feature (APM) Read +// CREATE/EDIT/DELETE --> Feature (APM) All + +// ANNOTATION API +// Feature (APM) All +// Index: `observability-annotations`. Privileges: `create_index`, `create_doc`, `manage`, and `read`. //// ******************************************************* //// +[role="xpack"] [[agent-config-api]] === Agent Configuration API @@ -274,6 +305,118 @@ POST /api/apm/settings/agent-configuration/search } -------------------------------------------------- +//// +******************************************************* +******************************************************* +//// + +[role="xpack"] +[[apm-annotation-api]] +=== Annotation API + +The Annotation API allows you to annotate visualizations in the APM app with significant events, like deployments, +allowing you to easily see how these events are impacting the performance of your existing applications. + +The following APIs are available: + +* <> to create an annotation for APM. +// * <> POST /api/observability/annotation +// * <> GET /api/observability/annotation/:id +// * <> DELETE /api/observability/annotation/:id + +By default, annotations are stored in a newly created `observability-annotations` index. +The name of this index can be changed in your `config.yml` by editing `xpack.observability.annotations.index`. + //// ******************************************************* //// + +[[apm-annotation-create]] +==== Create or update annotation + +[[apm-annotation-config-req]] +===== Request + +`POST /api/apm/services/:serviceName/annotation` + +[role="child_attributes"] +[[apm-annotation-config-req-body]] +===== Request body + +`service`:: +(required, object) Service identifying the configuration to create or update. ++ +.Properties of `service` +[%collapsible%open] +====== +`version` ::: + (required, string) Name of service. + +`environment` ::: + (optional, string) Environment of service. +====== + +`@timestamp`:: +(required, string) The date and time of the annotation. Must be in https://www.w3.org/TR/NOTE-datetime[ISO 8601] format. + +`message`:: +(optional, string) The message displayed in the annotation. Defaults to `service.version`. + +`tags`:: +(optional, array) Tags are used by the APM app to distinguish APM annotations from other annotations. +Tags may have additional functionality in future releases. Defaults to `[apm]`. +While you can add additional tags, you cannot remove the `apm` tag. + +[[apm-annotation-config-example]] +===== Example + +The following example creates an annotation for a service named `opbeans-java`. + +[source,console] +-------------------------------------------------- +POST /api/apm/services/opbeans-java/annotation +{ + "@timestamp": "2020-05-08T10:31:30.452Z", + "service": { + "version": "1.2" + }, + "message": "Deployment 1.2", + "tags": [ + "elastic.co", "customer" + ] +} +-------------------------------------------------- + +[[apm-annotation-config-body]] +===== Response body + +[source,js] +-------------------------------------------------- +{ + "_index": "observability-annotations", + "_id": "Lc9I93EBh6DbmkeV7nFX", + "_version": 1, + "_seq_no": 12, + "_primary_term": 1, + "found": true, + "_source": { + "message": "Deployment 1.2", + "@timestamp": "2020-05-08T10:31:30.452Z", + "service": { + "version": "1.2", + "name": "opbeans-java" + }, + "tags": [ + "apm", + "elastic.co", + "customer" + ], + "annotation": { + "type": "deployment" + }, + "event": { + "created": "2020-05-09T02:34:43.937Z" + } + } +} +-------------------------------------------------- diff --git a/docs/apm/deployment-annotations.asciidoc b/docs/apm/deployment-annotations.asciidoc index 6feadf8463226b..9abcd9f6efc740 100644 --- a/docs/apm/deployment-annotations.asciidoc +++ b/docs/apm/deployment-annotations.asciidoc @@ -3,7 +3,7 @@ === Track deployments with annotations ++++ -Track deployments +Track deployments with annotations ++++ For enhanced visibility into your deployments, we offer deployment annotations on all transaction charts. @@ -11,7 +11,11 @@ This feature automatically tags new deployments, so you can easily see if your d for an end-user, or if the memory/CPU footprint of your application has changed. Being able to identify bad deployments quickly enables you to rollback and fix issues without causing costly outages. -Deployment annotations are automatically enabled, and appear when the `service.version` of your app changes. +Deployment annotations are enabled by default, and can be created with the <>. +If there are no created annotations for the selected time period, +the APM app will automatically annotate your data if the `service.version` of your application changes. + +NOTE: If custom annotations have been created for the selected time period, any derived annotations, i.e., those created automatically when `service.version` changes, will not be shown. [role="screenshot"] image::apm/images/apm-transaction-annotation.png[Example view of transactions annotation in the APM app in Kibana] diff --git a/docs/apm/images/apm-agent-configuration.png b/docs/apm/images/apm-agent-configuration.png index ded0553219a031..05518cb924d1b1 100644 Binary files a/docs/apm/images/apm-agent-configuration.png and b/docs/apm/images/apm-agent-configuration.png differ diff --git a/docs/apm/images/apm-alert.png b/docs/apm/images/apm-alert.png index 4cee7214637f8e..43c6faa41c75ee 100644 Binary files a/docs/apm/images/apm-alert.png and b/docs/apm/images/apm-alert.png differ diff --git a/docs/apm/images/apm-errors-overview.png b/docs/apm/images/apm-errors-overview.png index 905487d2802bce..90f16b81e9f50e 100644 Binary files a/docs/apm/images/apm-errors-overview.png and b/docs/apm/images/apm-errors-overview.png differ diff --git a/docs/apm/images/apm-query-bar.png b/docs/apm/images/apm-query-bar.png index 57bac78ea12814..313ee7d4b8fc83 100644 Binary files a/docs/apm/images/apm-query-bar.png and b/docs/apm/images/apm-query-bar.png differ diff --git a/docs/apm/images/apm-services-overview.png b/docs/apm/images/apm-services-overview.png index 19068ce8f69db9..48236522ddfbb8 100644 Binary files a/docs/apm/images/apm-services-overview.png and b/docs/apm/images/apm-services-overview.png differ diff --git a/docs/apm/images/apm-settings.png b/docs/apm/images/apm-settings.png new file mode 100644 index 00000000000000..4eaef9ec15ac53 Binary files /dev/null and b/docs/apm/images/apm-settings.png differ diff --git a/docs/apm/images/apm-setup.png b/docs/apm/images/apm-setup.png index feff3d47b62e26..3f5f7761427de3 100644 Binary files a/docs/apm/images/apm-setup.png and b/docs/apm/images/apm-setup.png differ diff --git a/docs/apm/images/apm-traces.png b/docs/apm/images/apm-traces.png index ba3bbff482af3d..6219be5b6d6e49 100644 Binary files a/docs/apm/images/apm-traces.png and b/docs/apm/images/apm-traces.png differ diff --git a/docs/apm/images/apm-transaction-annotation.png b/docs/apm/images/apm-transaction-annotation.png index bc71b1d2169c49..8913770517ff6f 100644 Binary files a/docs/apm/images/apm-transaction-annotation.png and b/docs/apm/images/apm-transaction-annotation.png differ diff --git a/docs/apm/images/apm-transaction-response-dist.png b/docs/apm/images/apm-transaction-response-dist.png index 2309ec2435c81c..ecf5a4af2c25df 100644 Binary files a/docs/apm/images/apm-transaction-response-dist.png and b/docs/apm/images/apm-transaction-response-dist.png differ diff --git a/docs/apm/images/apm-transactions-overview.png b/docs/apm/images/apm-transactions-overview.png index c3c10fcb35ea83..b3b6ca22c4f635 100644 Binary files a/docs/apm/images/apm-transactions-overview.png and b/docs/apm/images/apm-transactions-overview.png differ diff --git a/docs/apm/images/jvm-metrics-overview.png b/docs/apm/images/jvm-metrics-overview.png new file mode 100644 index 00000000000000..9c8ba4a12a2629 Binary files /dev/null and b/docs/apm/images/jvm-metrics-overview.png differ diff --git a/docs/apm/images/jvm-metrics.png b/docs/apm/images/jvm-metrics.png index 0ca2147ae0e43c..1720e1370ff901 100644 Binary files a/docs/apm/images/jvm-metrics.png and b/docs/apm/images/jvm-metrics.png differ diff --git a/docs/apm/metrics.asciidoc b/docs/apm/metrics.asciidoc index e82a4fbd5c291b..e64cbc846960d4 100644 --- a/docs/apm/metrics.asciidoc +++ b/docs/apm/metrics.asciidoc @@ -11,8 +11,12 @@ For example, you might be able to correlate a high number of errors with a long [role="screenshot"] image::apm/images/apm-metrics.png[Example view of the Metrics overview in APM app in Kibana] -If you're using the Java Agent, the metrics view focuses on JVMs. -A detailed view of metrics per JVM makes it much easier to analyze the provided metrics: +If you're using the Java Agent, you can view metrics for each JVM. + +[role="screenshot"] +image::apm/images/jvm-metrics-overview.png[Example view of the Metrics overview for the Java Agent] + +Breaking down metrics by JVM makes it much easier to analyze the provided metrics: CPU usage, memory usage, heap or non-heap memory, thread count, garbage collection rate, and garbage collection time spent per minute. diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md index f36351c8b8f063..055ad9f37e654f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md @@ -6,7 +6,7 @@ Returns an URL to a given app, including the global base path. By default, the URL is relative (/basePath/app/my-app). Use the `absolute` option to generate an absolute url (http://host:port/basePath/app/my-app) -Note that when generating absolute urls, the protocol, host and port are determined from the browser location. +Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md index a93bc61bac5279..6f45bab3ebd2d0 100644 --- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md @@ -22,7 +22,8 @@ export interface ApplicationStart | Method | Description | | --- | --- | -| [getUrlForApp(appId, options)](./kibana-plugin-core-public.applicationstart.geturlforapp.md) | Returns an URL to a given app, including the global base path. By default, the URL is relative (/basePath/app/my-app). Use the absolute option to generate an absolute url (http://host:port/basePath/app/my-app)Note that when generating absolute urls, the protocol, host and port are determined from the browser location. | +| [getUrlForApp(appId, options)](./kibana-plugin-core-public.applicationstart.geturlforapp.md) | Returns an URL to a given app, including the global base path. By default, the URL is relative (/basePath/app/my-app). Use the absolute option to generate an absolute url (http://host:port/basePath/app/my-app)Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. | | [navigateToApp(appId, options)](./kibana-plugin-core-public.applicationstart.navigatetoapp.md) | Navigate to a given app | +| [navigateToUrl(url)](./kibana-plugin-core-public.applicationstart.navigatetourl.md) | Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible.If all these criteria are true for the given url: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's appRoute configuration)Then a SPA navigation will be performed using navigateToApp using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using window.location.assign | | [registerMountContext(contextName, provider)](./kibana-plugin-core-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md new file mode 100644 index 00000000000000..86b86776b0b12c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md @@ -0,0 +1,45 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ApplicationStart](./kibana-plugin-core-public.applicationstart.md) > [navigateToUrl](./kibana-plugin-core-public.applicationstart.navigatetourl.md) + +## ApplicationStart.navigateToUrl() method + +Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible. + +If all these criteria are true for the given url: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) + +Then a SPA navigation will be performed using `navigateToApp` using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using `window.location.assign` + +Signature: + +```typescript +navigateToUrl(url: string): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| url | string | an absolute url, or a relative path, to navigate to. | + +Returns: + +`Promise` + +## Example + + +```ts +// current url: `https://kibana:8080/base-path/s/my-space/app/dashboard` + +// will call `application.navigateToApp('discover', { path: '/some-path?foo=bar'})` +application.navigateToUrl('https://kibana:8080/base-path/s/my-space/app/discover/some-path?foo=bar') +application.navigateToUrl('/base-path/s/my-space/app/discover/some-path?foo=bar') + +// will perform a full page reload using `window.location.assign` +application.navigateToUrl('https://elsewhere:8080/base-path/s/my-space/app/discover/some-path') // origin does not match +application.navigateToUrl('/app/discover/some-path') // does not include the current basePath +application.navigateToUrl('/base-path/s/my-space/app/unknown-app/some-path') // unknown application + +``` + diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.doclinks.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.doclinks.md new file mode 100644 index 00000000000000..b239319c427fe4 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.doclinks.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreSetup](./kibana-plugin-core-public.coresetup.md) > [docLinks](./kibana-plugin-core-public.coresetup.doclinks.md) + +## CoreSetup.docLinks property + +[DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) + +Signature: + +```typescript +docLinks: DocLinksSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index 870fa33dce9000..4f981b5a40139f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -18,6 +18,7 @@ export interface CoreSetupApplicationSetup | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | | [context](./kibana-plugin-core-public.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-core-public.contextsetup.md) | +| [docLinks](./kibana-plugin-core-public.coresetup.doclinks.md) | DocLinksSetup | [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) | | [fatalErrors](./kibana-plugin-core-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | | [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | StartServicesAccessor<TPluginsStart, TStart> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) | | [http](./kibana-plugin-core-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.doc_link_version.md b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.doc_link_version.md new file mode 100644 index 00000000000000..c8d13bab92b058 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.doc_link_version.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) > [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinkssetup.doc_link_version.md) + +## DocLinksSetup.DOC\_LINK\_VERSION property + +Signature: + +```typescript +readonly DOC_LINK_VERSION: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.elastic_website_url.md b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.elastic_website_url.md new file mode 100644 index 00000000000000..d8493148bae107 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.elastic_website_url.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) > [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinkssetup.elastic_website_url.md) + +## DocLinksSetup.ELASTIC\_WEBSITE\_URL property + +Signature: + +```typescript +readonly ELASTIC_WEBSITE_URL: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.links.md similarity index 94% rename from docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md rename to docs/development/core/public/kibana-plugin-core-public.doclinkssetup.links.md index b43c484f8de7f9..fd05ae139ba215 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.links.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) > [links](./kibana-plugin-core-public.doclinksstart.links.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) > [links](./kibana-plugin-core-public.doclinkssetup.links.md) -## DocLinksStart.links property +## DocLinksSetup.links property Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.md b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.md new file mode 100644 index 00000000000000..1114e05589c4b7 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.doclinkssetup.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) + +## DocLinksSetup interface + + +Signature: + +```typescript +export interface DocLinksSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinkssetup.doc_link_version.md) | string | | +| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinkssetup.elastic_website_url.md) | string | | +| [links](./kibana-plugin-core-public.doclinkssetup.links.md) | {
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
} | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.doc_link_version.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.doc_link_version.md deleted file mode 100644 index 8140b3fcf380f9..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.doc_link_version.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) > [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) - -## DocLinksStart.DOC\_LINK\_VERSION property - -Signature: - -```typescript -readonly DOC_LINK_VERSION: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.elastic_website_url.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.elastic_website_url.md deleted file mode 100644 index af770ed3055aad..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.elastic_website_url.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) > [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) - -## DocLinksStart.ELASTIC\_WEBSITE\_URL property - -Signature: - -```typescript -readonly ELASTIC_WEBSITE_URL: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index 69bc4e473590c8..af2a41b691727d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -2,20 +2,11 @@ [Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) -## DocLinksStart interface +## DocLinksStart type Signature: ```typescript -export interface DocLinksStart +export declare type DocLinksStart = DocLinksSetup; ``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | -| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
} | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index eafc81447ee03e..b2524ec48c757d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -65,7 +65,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ContextSetup](./kibana-plugin-core-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | | [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | | [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | -| [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | +| [DocLinksSetup](./kibana-plugin-core-public.doclinkssetup.md) | | | [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | | [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | @@ -149,6 +149,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-core-public.chromehelpextensionmenugithublink.md) | | | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | +| [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | | [Freezable](./kibana-plugin-core-public.freezable.md) | | | [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientfactory.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientfactory.md index 09c6d63f03dd79..724c1ebbeadf44 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientfactory.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientfactory.md @@ -9,7 +9,8 @@ Describes the factory used to create instances of the Saved Objects Client. Signature: ```typescript -export declare type SavedObjectsClientFactory = ({ request, }: { +export declare type SavedObjectsClientFactory = ({ request, includedHiddenTypes, }: { request: KibanaRequest; + includedHiddenTypes?: string[]; }) => SavedObjectsClientContract; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.includedhiddentypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.includedhiddentypes.md new file mode 100644 index 00000000000000..a9483e34b38ced --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.includedhiddentypes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsClientProviderOptions](./kibana-plugin-core-server.savedobjectsclientprovideroptions.md) > [includedHiddenTypes](./kibana-plugin-core-server.savedobjectsclientprovideroptions.includedhiddentypes.md) + +## SavedObjectsClientProviderOptions.includedHiddenTypes property + +Signature: + +```typescript +includedHiddenTypes?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.md index 4291de765fd440..be1f73f0648439 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclientprovideroptions.md @@ -17,4 +17,5 @@ export interface SavedObjectsClientProviderOptions | Property | Type | Description | | --- | --- | --- | | [excludedWrappers](./kibana-plugin-core-server.savedobjectsclientprovideroptions.excludedwrappers.md) | string[] | | +| [includedHiddenTypes](./kibana-plugin-core-server.savedobjectsclientprovideroptions.includedhiddentypes.md) | string[] | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md index c4b19ca15910f3..e39ce020b930cc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md @@ -9,5 +9,5 @@ Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsre Signature: ```typescript -createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; +createInternalRepository: (includedHiddenTypes?: string[]) => ISavedObjectsRepository; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md index b9007d16d0234f..9cd0df90942777 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md @@ -9,5 +9,5 @@ Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsre Signature: ```typescript -createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; +createScopedRepository: (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.md index 35b29918edced3..dec768b68cd3af 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepositoryfactory.md @@ -16,6 +16,6 @@ export interface SavedObjectsRepositoryFactory | Property | Type | Description | | --- | --- | --- | -| [createInternalRepository](./kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md) | (extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | -| [createScopedRepository](./kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | +| [createInternalRepository](./kibana-plugin-core-server.savedobjectsrepositoryfactory.createinternalrepository.md) | (includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | +| [createScopedRepository](./kibana-plugin-core-server.savedobjectsrepositoryfactory.createscopedrepository.md) | (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md index 4467dd23d87b6b..d03e9ca223c530 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md @@ -9,5 +9,5 @@ Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsre Signature: ```typescript -createInternalRepository: (extraTypes?: string[]) => ISavedObjectsRepository; +createInternalRepository: (includedHiddenTypes?: string[]) => ISavedObjectsRepository; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md index 2840a377026e7c..762f77b98e74d3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md @@ -9,7 +9,7 @@ Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsre Signature: ```typescript -createScopedRepository: (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository; +createScopedRepository: (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md index 5f592adf7acd99..17655bb4878a7d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md @@ -16,8 +16,8 @@ export interface SavedObjectsServiceStart | Property | Type | Description | | --- | --- | --- | -| [createInternalRepository](./kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md) | (extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | -| [createScopedRepository](./kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md) | (req: KibanaRequest, extraTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | +| [createInternalRepository](./kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md) | (includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | +| [createScopedRepository](./kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md) | (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | | [createSerializer](./kibana-plugin-core-server.savedobjectsservicestart.createserializer.md) | () => SavedObjectsSerializer | Creates a [serializer](./kibana-plugin-core-server.savedobjectsserializer.md) that is aware of all registered types. | | [getScopedClient](./kibana-plugin-core-server.savedobjectsservicestart.getscopedclient.md) | (req: KibanaRequest, options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract | Creates a [Saved Objects client](./kibana-plugin-core-server.savedobjectsclientcontract.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. If other plugins have registered Saved Objects client wrappers, these will be applied to extend the functionality of the client.A client that is already scoped to the incoming request is also exposed from the route handler context see [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md). | | [getTypeRegistry](./kibana-plugin-core-server.savedobjectsservicestart.gettyperegistry.md) | () => ISavedObjectTypeRegistry | Returns the [registry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) containing all registered [saved object types](./kibana-plugin-core-server.savedobjectstype.md) | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md index 0d5e0e42af27fa..b015ebfcbaada2 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "indexPatterns" | "refreshInterval" | "customSubmitButton" | "screenTitle" | "dataTestSubj" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "onRefresh" | "timeHistory" | "onFiltersUpdated" | "onRefreshChange">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "customSubmitButton" | "screenTitle" | "dataTestSubj" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "timeHistory" | "onFiltersUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; } ``` diff --git a/docs/settings/apm-settings.asciidoc b/docs/settings/apm-settings.asciidoc index 8844fcd03ae9a2..b7819304852439 100644 --- a/docs/settings/apm-settings.asciidoc +++ b/docs/settings/apm-settings.asciidoc @@ -43,29 +43,32 @@ Changing these settings may disable features of the APM App. | `xpack.apm.enabled` | Set to `false` to disable the APM app. Defaults to `true`. -| `xpack.apm.ui.enabled` +| `xpack.apm.ui.enabled` {ess-icon} | Set to `false` to hide the APM app from the menu. Defaults to `true`. | `xpack.apm.ui.transactionGroupBucketSize` | Number of top transaction groups displayed in the APM app. Defaults to `100`. -| `xpack.apm.ui.maxTraceItems` +| `xpack.apm.ui.maxTraceItems` {ess-icon} | Maximum number of child items displayed when viewing trace details. Defaults to `1000`. -| `apm_oss.indexPattern` +| `xpack.observability.annotations.index` + | Index name where Observability annotations are stored. Defaults to `observability-annotations`. + +| `apm_oss.indexPattern` {ess-icon} | The index pattern used for integrations with Machine Learning and Query Bar. It must match all apm indices. Defaults to `apm-*`. -| `apm_oss.errorIndices` +| `apm_oss.errorIndices` {ess-icon} | Matcher for all {apm-server-ref}/error-indices.html[error indices]. Defaults to `apm-*`. | `apm_oss.onboardingIndices` | Matcher for all onboarding indices. Defaults to `apm-*`. -| `apm_oss.spanIndices` +| `apm_oss.spanIndices` {ess-icon} | Matcher for all {apm-server-ref}/span-indices.html[span indices]. Defaults to `apm-*`. -| `apm_oss.transactionIndices` +| `apm_oss.transactionIndices` {ess-icon} | Matcher for all {apm-server-ref}/transaction-indices.html[transaction indices]. Defaults to `apm-*`. | `apm_oss.metricsIndices` diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index 7c50dbf542d0d6..da109331ae0fbf 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -126,16 +126,22 @@ control the capturing process. [cols="2*<"] |=== | `xpack.reporting.capture.timeouts.openUrl` - | How long to allow the Reporting browser to wait for the initial data of the - {kib} page to load. Defaults to `30000` (30 seconds). + | Specify how long to allow the Reporting browser to wait for the "Loading..." screen + to dismiss and find the initial data for the Kibana page. If the time is + exceeded, a page screenshot is captured showing the current state, and the download link shows a warning message. + Defaults to `30000` (30 seconds). | `xpack.reporting.capture.timeouts.waitForElements` - | How long to allow the Reporting browser to wait for the visualization panels to - load on the {kib} page. Defaults to `30000` (30 seconds). + | Specify how long to allow the Reporting browser to wait for all visualization + panels to load on the Kibana page. If the time is exceeded, a page screenshot + is captured showing the current state, and the download link shows a warning message. Defaults to `30000` (30 + seconds). | `xpack.reporting.capture.timeouts.renderComplete` - | How long to allow the Reporting browser to wait for each visualization to - signal that it is done renderings. Defaults to `30000` (30 seconds). + | Specify how long to allow the Reporting browser to wait for all visualizations to + fetch and render the data. If the time is exceeded, a + page screenshot is captured showing the current state, and the download link shows a warning message. Defaults to + `30000` (30 seconds). |=== diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index cc662af08b8f19..6596f93a88f515 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -225,11 +225,11 @@ If you configure a custom index, the name must be lowercase, and conform to the {es} {ref}/indices-create-index.html[index name limitations]. *Default: `".kibana"`* -| `kibana.autocompleteTimeout:` +| `kibana.autocompleteTimeout:` {ess-icon} | Time in milliseconds to wait for autocomplete suggestions from {es}. This value must be a whole number greater than zero. *Default: `"1000"`* -| `kibana.autocompleteTerminateAfter:` +| `kibana.autocompleteTerminateAfter:` {ess-icon} | Maximum number of documents loaded by each shard to generate autocomplete suggestions. This value must be a whole number greater than zero. *Default: `"100000"`* @@ -300,11 +300,11 @@ suppress all logging output. *Default: `false`* (for example, `America/Los_Angeles`) to log events using that timezone. For a list of timezones, refer to https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. *Default: `UTC`* -| [[logging-verbose]] `logging.verbose:` +| [[logging-verbose]] `logging.verbose:` {ece-icon} | Set to `true` to log all events, including system usage information and all -requests. Supported on {ece}. *Default: `false`* +requests. *Default: `false`* -| `map.includeElasticMapsService:` +| `map.includeElasticMapsService:` {ess-icon} | Set to `false` to disable connections to Elastic Maps Service. When `includeElasticMapsService` is turned off, only the vector layers configured by `map.regionmap` and the tile layer configured by `map.tilemap.url` are available in <>. *Default: `true`* @@ -313,9 +313,9 @@ and the tile layer configured by `map.tilemap.url` are available in <> Elastic Maps Service requests through the {kib} server. *Default: `false`* -| [[regionmap-settings]] `map.regionmap:` +| [[regionmap-settings]] `map.regionmap:` {ess-icon} {ece-icon} | Specifies additional vector layers for -use in <> visualizations. Supported on {ece}. Each layer +use in <> visualizations. Each layer object points to an external vector file that contains a geojson FeatureCollection. The file must use the https://en.wikipedia.org/wiki/World_Geodetic_System[WGS84 coordinate reference system (ESPG:4326)] @@ -343,20 +343,19 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-ES-map]] `map.includeElasticMapsService:` +| [[regionmap-ES-map]] `map.includeElasticMapsService:` {ece-icon} | Turns on or off whether layers from the Elastic Maps Service should be included in the vector -layer option list. Supported on {ece}. By turning this off, +layer option list. By turning this off, only the layers that are configured here will be included. The default is `true`. This also affects whether tile-service from the Elastic Maps Service will be available. -| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` +| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` {ess-icon} {ece-icon} | Optional. References the originating source of the geojson file. -Supported on {ece}. -| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` +| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` {ess-icon} {ece-icon} | Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson -features you wish to expose. Supported on {ece}. The following shows how to define multiple +features you wish to expose. The following shows how to define multiple properties: |=== @@ -379,44 +378,44 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` +| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` {ess-icon} {ece-icon} | Mandatory. The human readable text that is shown under the Options tab when -building the Region Map visualization. Supported on {ece}. +building the Region Map visualization. -| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` +| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` {ess-icon} {ece-icon} | Mandatory. This value is used to do an inner-join between the document stored in {es} and the geojson file. For example, if the field in the geojson is called `Location` and has city names, there must be a field in {es} that holds the same values that {kib} can then use to lookup for the geoshape -data. Supported on {ece}. +data. -| [[regionmap-name]] `map.regionmap.layers[].name:` +| [[regionmap-name]] `map.regionmap.layers[].name:` {ess-icon} {ece-icon} | Mandatory. A description of -the map being provided. Supported on {ece}. +the map being provided. -| [[regionmap-url]] `map.regionmap.layers[].url:` +| [[regionmap-url]] `map.regionmap.layers[].url:` {ess-icon} {ece-icon} | Mandatory. The location of the -geojson file as provided by a webserver. Supported on {ece}. +geojson file as provided by a webserver. -| [[tilemap-settings]] `map.tilemap.options.attribution:` - | The map attribution string. Supported on {ece}. +| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} {ece-icon} + | The map attribution string. *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* -| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` - | The maximum zoom level. Supported on {ece}. *Default: `10`* +| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon} {ece-icon} + | The maximum zoom level. *Default: `10`* -| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` - | The minimum zoom level. Supported on {ece}. *Default: `1`* +| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` {ess-icon} {ece-icon} + | The minimum zoom level. *Default: `1`* -| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` +| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` {ess-icon} {ece-icon} | An array of subdomains used by the tile service. Specify the position of the subdomain the URL with -the token `{s}`. Supported on {ece}. +the token `{s}`. -| [[tilemap-url]] `map.tilemap.url:` +| [[tilemap-url]] `map.tilemap.url:` {ess-icon} {ece-icon} | The URL to the tileservice that {kib} uses -to display map tiles in tilemap visualizations. Supported on {ece}. By default, +to display map tiles in tilemap visualizations. By default, {kib} reads this URL from an external metadata service, but users can override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"` @@ -451,7 +450,7 @@ deprecation warning at startup. This setting cannot end in a slash (`/`). proxy sitting in front of it. This determines whether HTTP compression may be used for responses, based on the request `Referer` header. This setting may not be used when `server.compression.enabled` is set to `false`. *Default: `none`* -| `server.customResponseHeaders:` +| `server.customResponseHeaders:` {ess-icon} | Header names and values to send on all responses to the client from the {kib} server. *Default: `{}`* @@ -610,7 +609,7 @@ us improve your user experience. Your data is never shared with anyone. Set to `false` to disable telemetry capabilities entirely. You can alternatively opt out through *Advanced Settings*. *Default: `true`* -| `vis_type_vega.enableExternalUrls:` +| `vis_type_vega.enableExternalUrls:` {ess-icon} | Set this value to true to allow Vega to use any URL to access external data sources and images. When false, Vega can only get data from {es}. *Default: `false`* @@ -622,7 +621,7 @@ disable the License Management UI. *Default: `true`* | Set this value to false to disable the Rollup UI. *Default: true* -| `i18n.locale` +| `i18n.locale` {ess-icon} | Set this value to change the {kib} interface language. Valid locales are: `en`, `zh-CN`, `ja-JP`. *Default: `en`* diff --git a/docs/user/getting-started.asciidoc b/docs/user/getting-started.asciidoc index d426ec111351cc..0eb823dcc720ff 100644 --- a/docs/user/getting-started.asciidoc +++ b/docs/user/getting-started.asciidoc @@ -8,18 +8,9 @@ Ready to try out {kib} and see what it can do? To quickest way to get started wi [float] [[cloud-set-up]] -== Set up on Cloud +== Set up on cloud -To access {kib} in a single click, run our hosted Elasticsearch Service on Elastic Cloud. - -. Log into the link:https://cloud.elastic.co/[Elasticsearch Service Console]. -If you need an account, register for a link:https://www.elastic.co/cloud/elasticsearch-service/signup[free 14-day trial]. - -. Click *Create deployment*, then give your deployment a name. - -. To use the default options, click *Create deployment*. You can modify the other deployment options, but the default options are great to get started. - -Be sure to copy down the password for the `elastic` user and Cloud ID information. You'll need that later. +include::{docs-root}/shared/cloud/ess-getting-started.asciidoc[] [float] [[get-data-in]] diff --git a/docs/user/monitoring/configuring-monitoring.asciidoc b/docs/user/monitoring/configuring-monitoring.asciidoc index de9e99117fc990..776a76b24c4ec3 100644 --- a/docs/user/monitoring/configuring-monitoring.asciidoc +++ b/docs/user/monitoring/configuring-monitoring.asciidoc @@ -8,8 +8,8 @@ If you enable the {monitor-features} in your cluster, there are two methods to collect metrics about {kib}: -* <> -* <> +* <> +* <> You can also use {kib} to <>. @@ -17,6 +17,6 @@ You can also use {kib} to To learn about monitoring in general, see {ref}/monitor-elasticsearch-cluster.html[Monitor a cluster]. -include::monitoring-kibana.asciidoc[] include::monitoring-metricbeat.asciidoc[] include::viewing-metrics.asciidoc[] +include::monitoring-kibana.asciidoc[] diff --git a/docs/user/monitoring/monitoring-kibana.asciidoc b/docs/user/monitoring/monitoring-kibana.asciidoc index 9aa10289d299b3..bb619ac79e143e 100644 --- a/docs/user/monitoring/monitoring-kibana.asciidoc +++ b/docs/user/monitoring/monitoring-kibana.asciidoc @@ -1,15 +1,15 @@ [role="xpack"] [[monitoring-kibana]] -=== Collecting {kib} monitoring data +=== Collecting monitoring data using legacy collectors ++++ -Collecting monitoring data +Legacy collection methods ++++ If you enable the Elastic {monitor-features} in your cluster, you can optionally collect metrics about {kib}. The following method involves sending the metrics to the production cluster, -which ultimately routes them to the monitoring cluster. For an alternative +which ultimately routes them to the monitoring cluster. For the recommended method, see <>. To learn about monitoring in general, see diff --git a/docs/user/security/api-keys/index.asciidoc b/docs/user/security/api-keys/index.asciidoc index c00f58cf598e38..b8d6649a3fb857 100644 --- a/docs/user/security/api-keys/index.asciidoc +++ b/docs/user/security/api-keys/index.asciidoc @@ -3,18 +3,18 @@ === API Keys -API keys enable you to create secondary credentials so that you can send -requests on behalf of the user. Secondary credentials have -the same or lower access rights. +API keys enable you to create secondary credentials so that you can send +requests on behalf of the user. Secondary credentials have +the same or lower access rights. For example, if you extract data from an {es} cluster on a daily -basis, you might create an API key tied to your credentials, -configure it with minimum access, +basis, you might create an API key tied to your credentials, +configure it with minimum access, and then put the API credentials into a cron job. -Or, you might create API keys to automate ingestion of new data from -remote sources, without a live user interaction. +Or, you might create API keys to automate ingestion of new data from +remote sources, without a live user interaction. -You can create API keys from the {kib} Console. To view and invalidate +You can create API keys from the {kib} Console. To view and invalidate API keys, use *Management > Security > API Keys*. [role="screenshot"] @@ -24,63 +24,80 @@ image:user/security/api-keys/images/api-keys.png["API Keys UI"] [[api-keys-service]] === {es} API key service -The {es} API key service is automatically enabled when you configure -{ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. +The {es} API key service is automatically enabled when you configure +{ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. This ensures that clients are unable to send API keys in clear-text. -When HTTPS connections are not enabled between {kib} and {es}, +When HTTPS connections are not enabled between {kib} and {es}, you cannot create or manage API keys, and you get an error message. -For more information, see the -{ref}/security-api-create-api-key.html[{es} API key documentation], +For more information, see the +{ref}/security-api-create-api-key.html[{es} API key documentation], or contact your system administrator. [float] [[api-keys-security-privileges]] === Security privileges -You must have the `manage_security`, `manage_api_key`, or the `manage_own_api_key` -cluster privileges to use API keys in {kib}. You can manage roles in -*Management > Security > Roles*, or use the <>. +You must have the `manage_security`, `manage_api_key`, or the `manage_own_api_key` +cluster privileges to use API keys in {kib}. You can manage roles in +*Management > Security > Roles*, or use the <>. [float] [[create-api-key]] === Create an API key -You can {ref}/security-api-create-api-key.html[create an API key] from -the Kibana Console. For example: +You can {ref}/security-api-create-api-key.html[create an API key] from +the {kib} Console. This example shows how to create an API key +to authenticate to a <>. [source,js] POST /_security/api_key { - "name": "my_api_key", - "expiration": "1d" + "name": "kibana_api_key", } -This creates an API key with the name `my_api_key` that -expires after one day. API key names must be globally unique. -An expiration date is optional and follows {ref}/common-options.html#time-units[{es} time unit format]. +This creates an API key with the +name `kibana_api_key`. API key +names must be globally unique. +An expiration date is optional and follows +{ref}/common-options.html#time-units[{es} time unit format]. When an expiration is not provided, the API key does not expire. +The response should look something like this: + +[source,js] +{ + "id" : "XFcbCnIBnbwqt2o79G4q", + "name" : "kibana_api_key", + "api_key" : "FD6P5UA4QCWlZZQhYF3YGw" +} + +Now, you can use the API key to request {kib} roles. You will need +to base64-encode the `id` and `api_key` provided in the response +and add it to your request as an authorization header. For example: + +[source,js] +curl --location --request GET 'http://localhost:5601/api/security/role' \ +--header 'Content-Type: application/json;charset=UTF-8' \ +--header 'kbn-xsrf: true' \ +--header 'Authorization: ApiKey aVZlLUMzSUJuYndxdDJvN0k1bU46aGxlYUpNS2lTa2FKeVZua1FnY1VEdw==' \ + [float] [[view-api-keys]] === View and invalidate API keys -The *API Keys* UI lists your API keys, including the name, date created, +The *API Keys* feature in Kibana lists your API keys, including the name, date created, and expiration date. If an API key expires, its status changes from `Active` to `Expired`. -If you have `manage_security` or `manage_api_key` permissions, -you can view the API keys of all users, and see which API key was +If you have `manage_security` or `manage_api_key` permissions, +you can view the API keys of all users, and see which API key was created by which user in which realm. If you have only the `manage_own_api_key` permission, you see only a list of your own keys. -You can invalidate API keys individually or in bulk. +You can invalidate API keys individually or in bulk. Invalidated keys are deleted in batch after seven days. [role="screenshot"] image:user/security/api-keys/images/api-key-invalidate.png["API Keys invalidate"] -You cannot modify an API key. If you need additional privileges, +You cannot modify an API key. If you need additional privileges, you must create a new key with the desired configuration and invalidate the old key. - - - - diff --git a/examples/alerting_example/kibana.json b/examples/alerting_example/kibana.json index bcdb7c2f14a9c9..76c549adc79700 100644 --- a/examples/alerting_example/kibana.json +++ b/examples/alerting_example/kibana.json @@ -2,7 +2,6 @@ "id": "alertingExample", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["alerting_example"], "server": true, "ui": true, "requiredPlugins": ["triggers_actions_ui", "charts", "data", "alerting", "actions"], diff --git a/examples/alerting_example/package.json b/examples/alerting_example/package.json deleted file mode 100644 index 96187d847c1c41..00000000000000 --- a/examples/alerting_example/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "alerting_example", - "version": "1.0.0", - "main": "target/examples/alerting_example", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/alerting_example/public/alert_types/always_firing.tsx b/examples/alerting_example/public/alert_types/always_firing.tsx index b7add1f6d43cef..130519308d3c3c 100644 --- a/examples/alerting_example/public/alert_types/always_firing.tsx +++ b/examples/alerting_example/public/alert_types/always_firing.tsx @@ -71,7 +71,7 @@ export const AlwaysFiringExpression: React.FunctionComponent { + onChange={(event) => { setAlertParams('instances', event.target.valueAsNumber); }} /> diff --git a/examples/alerting_example/public/alert_types/astros.tsx b/examples/alerting_example/public/alert_types/astros.tsx index 3411c6722ccd61..2e263e454fa0c1 100644 --- a/examples/alerting_example/public/alert_types/astros.tsx +++ b/examples/alerting_example/public/alert_types/astros.tsx @@ -51,7 +51,7 @@ interface PeopleinSpaceParamsProps { } function isValueInEnum(enumeratin: Record, value: any): boolean { - return !!Object.values(enumeratin).find(enumVal => enumVal === value); + return !!Object.values(enumeratin).find((enumVal) => enumVal === value); } export function getAlertType(): AlertTypeModel { @@ -139,7 +139,7 @@ export const PeopleinSpaceExpression: React.FunctionComponent - errs.map(e => ( + errs.map((e) => (

{field}:`: ${errs}`

@@ -189,7 +189,7 @@ export const PeopleinSpaceExpression: React.FunctionComponent { + onChange={(event) => { setAlertParams('craft', event.target.value); setCraftTrigger({ craft: event.target.value, @@ -238,7 +238,7 @@ export const PeopleinSpaceExpression: React.FunctionComponent { + onChange={(event) => { setAlertParams('op', event.target.value); setOuterSpaceCapacity({ ...outerSpaceCapacityTrigger, @@ -258,7 +258,7 @@ export const PeopleinSpaceExpression: React.FunctionComponent { + onChange={(event) => { setAlertParams('outerSpaceCapacity', event.target.valueAsNumber); setOuterSpaceCapacity({ ...outerSpaceCapacityTrigger, diff --git a/examples/alerting_example/server/alert_types/astros.ts b/examples/alerting_example/server/alert_types/astros.ts index d22bc6164fa523..d25edc1e01b3f0 100644 --- a/examples/alerting_example/server/alert_types/astros.ts +++ b/examples/alerting_example/server/alert_types/astros.ts @@ -68,10 +68,7 @@ export const alertType: AlertType = { if (getOperator(op)(peopleInCraft.length, outerSpaceCapacity)) { peopleInCraft.forEach(({ craft, name }) => { - services - .alertInstanceFactory(name) - .replaceState({ craft }) - .scheduleActions('default'); + services.alertInstanceFactory(name).replaceState({ craft }).scheduleActions('default'); }); } diff --git a/examples/bfetch_explorer/kibana.json b/examples/bfetch_explorer/kibana.json index cbdd9be0e658ce..e2a6d3ebd7d47c 100644 --- a/examples/bfetch_explorer/kibana.json +++ b/examples/bfetch_explorer/kibana.json @@ -2,7 +2,6 @@ "id": "bfetchExplorer", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["bfetch_explorer"], "server": true, "ui": true, "requiredPlugins": ["bfetch"], diff --git a/examples/bfetch_explorer/package.json b/examples/bfetch_explorer/package.json deleted file mode 100644 index ea5a1b1848613b..00000000000000 --- a/examples/bfetch_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "bfetch_explorer", - "version": "1.0.0", - "main": "target/examples/bfetch_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/bfetch_explorer/public/components/count_until/index.tsx b/examples/bfetch_explorer/public/components/count_until/index.tsx index ce48ce9dfe61f5..73cbcf4cbdb1c4 100644 --- a/examples/bfetch_explorer/public/components/count_until/index.tsx +++ b/examples/bfetch_explorer/public/components/count_until/index.tsx @@ -82,7 +82,7 @@ export const CountUntil: React.FC = ({ fetchStreaming }) => { setData(Number(e.target.value))} + onChange={(e) => setData(Number(e.target.value))} /> diff --git a/examples/bfetch_explorer/public/components/double_integers/index.tsx b/examples/bfetch_explorer/public/components/double_integers/index.tsx index d8fbe33ec73be2..58940c23b1a6cf 100644 --- a/examples/bfetch_explorer/public/components/double_integers/index.tsx +++ b/examples/bfetch_explorer/public/components/double_integers/index.tsx @@ -49,18 +49,18 @@ export const DoubleIntegers: React.FC = ({ double }) => { setShowingResults(true); const nums = numbers .split('\n') - .map(num => num.trim()) + .map((num) => num.trim()) .filter(Boolean) .map(Number); counter.set(nums.length); - nums.forEach(num => { + nums.forEach((num) => { double({ num }).then( - result => { + (result) => { if (!isMounted()) return; counter.dec(); pushResult({ num, result }); }, - error => { + (error) => { if (!isMounted()) return; counter.dec(); pushResult({ num, error }); @@ -94,7 +94,7 @@ export const DoubleIntegers: React.FC = ({ double }) => { fullWidth placeholder="Enter numbers in milliseconds separated by new line" value={numbers} - onChange={e => setNumbers(e.target.value)} + onChange={(e) => setNumbers(e.target.value)} /> diff --git a/examples/bfetch_explorer/public/containers/app/index.tsx b/examples/bfetch_explorer/public/containers/app/index.tsx index a448c9e4f3a6a8..13dee8ad9e61f6 100644 --- a/examples/bfetch_explorer/public/containers/app/index.tsx +++ b/examples/bfetch_explorer/public/containers/app/index.tsx @@ -30,7 +30,7 @@ export const App: React.FC = () => { const routeElements: React.ReactElement[] = []; for (const { items } of routes) { for (const { id, component } of items) { - routeElements.push( component} />); + routeElements.push( component} />); } } diff --git a/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx index cc50698e05908e..029076adea666b 100644 --- a/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx +++ b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx @@ -39,7 +39,7 @@ export const Sidebar: React.FC = () => { id, name: title, isSelected: true, - items: items.map(route => ({ + items: items.map((route) => ({ id: route.id, name: route.title, onClick: () => history.push(`/${route.id}`), diff --git a/examples/bfetch_explorer/server/plugin.ts b/examples/bfetch_explorer/server/plugin.ts index bf3b7f50ca6c84..2bfb63edefa3d5 100644 --- a/examples/bfetch_explorer/server/plugin.ts +++ b/examples/bfetch_explorer/server/plugin.ts @@ -54,7 +54,7 @@ export class BfetchExplorerPlugin implements Plugin { // Validate inputs. if (num < 0) throw new Error('Invalid number'); // Wait number of specified milliseconds. - await new Promise(r => setTimeout(r, num)); + await new Promise((r) => setTimeout(r, num)); // Double the number and send it back. return { num: 2 * num }; }, diff --git a/examples/demo_search/kibana.json b/examples/demo_search/kibana.json index cb73274ed23f7e..cdf74121ea2db1 100644 --- a/examples/demo_search/kibana.json +++ b/examples/demo_search/kibana.json @@ -2,7 +2,6 @@ "id": "demoSearch", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["demoSearch"], "server": true, "ui": true, "requiredPlugins": ["data"], diff --git a/examples/demo_search/package.json b/examples/demo_search/package.json deleted file mode 100644 index d29ad55b32db2d..00000000000000 --- a/examples/demo_search/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "demo_data_search", - "version": "1.0.0", - "main": "target/examples/demo_data_search", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/demo_search/server/async_demo_search_strategy.ts b/examples/demo_search/server/async_demo_search_strategy.ts index d2d40891a5d939..7ed5062acba484 100644 --- a/examples/demo_search/server/async_demo_search_strategy.ts +++ b/examples/demo_search/server/async_demo_search_strategy.ts @@ -40,7 +40,7 @@ const totalMap = new Map(); export const asyncDemoSearchStrategyProvider: TSearchStrategyProvider = () => { return { - search: async request => { + search: async (request) => { const id = request.id ?? generateId(); const loaded = (loadedMap.get(id) ?? 0) + 1; @@ -52,7 +52,7 @@ export const asyncDemoSearchStrategyProvider: TSearchStrategyProvider { + cancel: async (id) => { loadedMap.delete(id); totalMap.delete(id); }, diff --git a/examples/demo_search/server/demo_search_strategy.ts b/examples/demo_search/server/demo_search_strategy.ts index 5b0883be1fc514..a1fd0e45dbc8e7 100644 --- a/examples/demo_search/server/demo_search_strategy.ts +++ b/examples/demo_search/server/demo_search_strategy.ts @@ -22,7 +22,7 @@ import { DEMO_SEARCH_STRATEGY } from '../common'; export const demoSearchStrategyProvider: TSearchStrategyProvider = () => { return { - search: request => { + search: (request) => { return Promise.resolve({ greeting: request.mood === 'happy' diff --git a/examples/embeddable_examples/kibana.json b/examples/embeddable_examples/kibana.json index f446e7f31ac8ef..489f768552b281 100644 --- a/examples/embeddable_examples/kibana.json +++ b/examples/embeddable_examples/kibana.json @@ -2,7 +2,6 @@ "id": "embeddableExamples", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["embeddable_examples"], "server": true, "ui": true, "requiredPlugins": ["embeddable"], diff --git a/examples/embeddable_examples/package.json b/examples/embeddable_examples/package.json deleted file mode 100644 index 055ee6d7315123..00000000000000 --- a/examples/embeddable_examples/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "embeddable_examples", - "version": "1.0.0", - "main": "target/examples/embeddable_examples", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/embeddable_examples/public/list_container/list_container_component.tsx b/examples/embeddable_examples/public/list_container/list_container_component.tsx index da27889a276036..ae4de1c765154b 100644 --- a/examples/embeddable_examples/public/list_container/list_container_component.tsx +++ b/examples/embeddable_examples/public/list_container/list_container_component.tsx @@ -40,7 +40,7 @@ function renderList( embeddableServices: EmbeddableStart ) { let number = 0; - const list = Object.values(panels).map(panel => { + const list = Object.values(panels).map((panel) => { const child = embeddable.getChild(panel.explicitInput.id); number++; return ( diff --git a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx index b2882c97ef501e..c059a884f08a27 100644 --- a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx +++ b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx @@ -55,7 +55,7 @@ function wrapSearchTerms(task: string, search?: string) { } function renderTasks(tasks: MultiTaskTodoInput['tasks'], search?: string) { - return tasks.map(task => ( + return tasks.map((task) => ( task.match(search)); + const match = tasks.find((task) => task.match(search)); if (match) return true; return false; diff --git a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx index 49dbce74788bfa..f5fe01734bfa58 100644 --- a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx +++ b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx @@ -65,12 +65,12 @@ export class SearchableListContainerComponentInner extends Component { + props.embeddable.getChildIds().forEach((id) => { checked[id] = false; const output = props.embeddable.getChild(id).getOutput(); hasMatch[id] = hasHasMatchOutput(output) && output.hasMatch; }); - props.embeddable.getChildIds().forEach(id => (checked[id] = false)); + props.embeddable.getChildIds().forEach((id) => (checked[id] = false)); this.state = { checked, hasMatch, @@ -78,13 +78,13 @@ export class SearchableListContainerComponentInner extends Component { + this.props.embeddable.getChildIds().forEach((id) => { this.subscriptions[id] = this.props.embeddable .getChild(id) .getOutput$() - .subscribe(output => { + .subscribe((output) => { if (hasHasMatchOutput(output)) { - this.setState(prevState => ({ + this.setState((prevState) => ({ hasMatch: { ...prevState.hasMatch, [id]: output.hasMatch, @@ -96,7 +96,7 @@ export class SearchableListContainerComponentInner extends Component sub.unsubscribe()); + Object.values(this.subscriptions).forEach((sub) => sub.unsubscribe()); } private updateSearch = (search: string) => { @@ -104,7 +104,7 @@ export class SearchableListContainerComponentInner extends Component { - Object.values(this.props.input.panels).map(panel => { + Object.values(this.props.input.panels).map((panel) => { if (this.state.checked[panel.explicitInput.id]) { this.props.embeddable.removeEmbeddable(panel.explicitInput.id); this.subscriptions[panel.explicitInput.id].unsubscribe(); @@ -115,7 +115,7 @@ export class SearchableListContainerComponentInner extends Component { const { input, embeddable } = this.props; const checked: { [key: string]: boolean } = {}; - Object.values(input.panels).map(panel => { + Object.values(input.panels).map((panel) => { const child = embeddable.getChild(panel.explicitInput.id); const output = child.getOutput(); if (hasHasMatchOutput(output) && output.hasMatch) { @@ -126,7 +126,7 @@ export class SearchableListContainerComponentInner extends Component { - this.setState(prevState => ({ checked: { ...prevState.checked, [id]: isChecked } })); + this.setState((prevState) => ({ checked: { ...prevState.checked, [id]: isChecked } })); }; public renderControls() { @@ -156,7 +156,7 @@ export class SearchableListContainerComponentInner extends Component this.updateSearch(ev.target.value)} + onChange={(ev) => this.updateSearch(ev.target.value)} /> @@ -183,7 +183,7 @@ export class SearchableListContainerComponentInner extends Component { + const list = Object.values(input.panels).map((panel) => { const childEmbeddable = embeddable.getChild(panel.explicitInput.id); id++; return childEmbeddable ? ( @@ -195,7 +195,7 @@ export class SearchableListContainerComponentInner extends Component this.toggleCheck(e.target.checked, childEmbeddable.id)} + onChange={(e) => this.toggleCheck(e.target.checked, childEmbeddable.id)} /> diff --git a/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx b/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx index bc577ca36d793d..a46c3ce9ed8e9f 100644 --- a/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx +++ b/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx @@ -34,7 +34,7 @@ function TaskInput({ onSave }: { onSave: (task: string) => void }) { data-test-subj="taskInputField" value={task} placeholder="Enter task here" - onChange={e => setTask(e.target.value)} + onChange={(e) => setTask(e.target.value)} /> onSave(task)}> Save @@ -69,7 +69,7 @@ export class TodoEmbeddableFactory */ public getExplicitInput = async () => { const { openModal } = await this.getStartServices(); - return new Promise<{ task: string }>(resolve => { + return new Promise<{ task: string }>((resolve) => { const onSave = (task: string) => resolve({ task }); const overlay = openModal( toMountPoint( diff --git a/examples/embeddable_explorer/kibana.json b/examples/embeddable_explorer/kibana.json index 6c27bcd39f12d0..3e4b074fb6b12d 100644 --- a/examples/embeddable_explorer/kibana.json +++ b/examples/embeddable_explorer/kibana.json @@ -2,7 +2,6 @@ "id": "embeddableExplorer", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["embeddable_explorer"], "server": false, "ui": true, "requiredPlugins": ["uiActions", "inspector", "embeddable", "embeddableExamples"], diff --git a/examples/embeddable_explorer/package.json b/examples/embeddable_explorer/package.json deleted file mode 100644 index 771c5c9be9c06e..00000000000000 --- a/examples/embeddable_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "embeddable_explorer", - "version": "1.0.0", - "main": "target/examples/embeddable_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/embeddable_explorer/public/app.tsx b/examples/embeddable_explorer/public/app.tsx index e18012b4b3d806..3fc7fbb3b89ef1 100644 --- a/examples/embeddable_explorer/public/app.tsx +++ b/examples/embeddable_explorer/public/app.tsx @@ -51,7 +51,7 @@ type NavProps = RouteComponentProps & { }; const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => { - const navItems = pages.map(page => ({ + const navItems = pages.map((page) => ({ id: page.id, name: page.title, onClick: () => history.push(`/${page.id}`), @@ -122,7 +122,7 @@ const EmbeddableExplorerApp = ({ ]; const routes = pages.map((page, i) => ( - page.component} /> + page.component} /> )); return ( diff --git a/examples/embeddable_explorer/public/embeddable_panel_example.tsx b/examples/embeddable_explorer/public/embeddable_panel_example.tsx index 54cd7c5b5b2c01..98f30632ebf431 100644 --- a/examples/embeddable_explorer/public/embeddable_panel_example.tsx +++ b/examples/embeddable_explorer/public/embeddable_panel_example.tsx @@ -84,7 +84,7 @@ export function EmbeddablePanelExample({ embeddableServices }: Props) { const factory = embeddableServices.getEmbeddableFactory(SEARCHABLE_LIST_CONTAINER); const promise = factory?.create(searchableInput); if (promise) { - promise.then(e => { + promise.then((e) => { if (ref.current) { setEmbeddable(e); } diff --git a/examples/embeddable_explorer/public/todo_embeddable_example.tsx b/examples/embeddable_explorer/public/todo_embeddable_example.tsx index 2af6c713593c68..f43a81c3e76512 100644 --- a/examples/embeddable_explorer/public/todo_embeddable_example.tsx +++ b/examples/embeddable_explorer/public/todo_embeddable_example.tsx @@ -82,7 +82,7 @@ export class TodoEmbeddableExample extends React.Component { icon: 'broom', title: 'Trash', }) - .then(embeddable => { + .then((embeddable) => { this.embeddable = embeddable; this.setState({ loading: false }); }); @@ -135,7 +135,7 @@ export class TodoEmbeddableExample extends React.Component { this.setState({ title: ev.target.value })} + onChange={(ev) => this.setState({ title: ev.target.value })} /> @@ -143,7 +143,7 @@ export class TodoEmbeddableExample extends React.Component { this.setState({ icon: ev.target.value })} + onChange={(ev) => this.setState({ icon: ev.target.value })} /> @@ -153,7 +153,7 @@ export class TodoEmbeddableExample extends React.Component { fullWidth resize="horizontal" data-test-subj="taskTodo" - onChange={ev => this.setState({ task: ev.target.value })} + onChange={(ev) => this.setState({ task: ev.target.value })} /> diff --git a/examples/search_explorer/kibana.json b/examples/search_explorer/kibana.json index ca8c6a5b242439..a8538d6b679610 100644 --- a/examples/search_explorer/kibana.json +++ b/examples/search_explorer/kibana.json @@ -2,7 +2,6 @@ "id": "searchExplorer", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["search_explorer"], "server": false, "ui": true, "requiredPlugins": ["data", "demoSearch"], diff --git a/examples/search_explorer/package.json b/examples/search_explorer/package.json deleted file mode 100644 index f3c71c5d181f8d..00000000000000 --- a/examples/search_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "searchExplorer", - "version": "1.0.0", - "main": "target/examples/search_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/search_explorer/public/application.tsx b/examples/search_explorer/public/application.tsx index ea6d65d9e21131..a7072936f268d3 100644 --- a/examples/search_explorer/public/application.tsx +++ b/examples/search_explorer/public/application.tsx @@ -51,7 +51,7 @@ type NavProps = RouteComponentProps & { }; const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => { - const navItems = pages.map(page => ({ + const navItems = pages.map((page) => ({ id: page.id, name: page.title, onClick: () => history.push(`/${page.id}`), @@ -103,7 +103,7 @@ const SearchApp = ({ basename, data, application }: SearchBarComponentParams) => ]; const routes = pages.map((page, i) => ( - buildPage(page)} /> + buildPage(page)} /> )); return ( diff --git a/examples/search_explorer/public/async_demo_strategy.tsx b/examples/search_explorer/public/async_demo_strategy.tsx index 40ddcc1f48fe7a..9cea556c32d54f 100644 --- a/examples/search_explorer/public/async_demo_strategy.tsx +++ b/examples/search_explorer/public/async_demo_strategy.tsx @@ -73,7 +73,7 @@ export class AsyncDemoStrategy extends React.Component { this.setState({ fibonacciNumbers: parseFloat(e.target.value) })} + onChange={(e) => this.setState({ fibonacciNumbers: parseFloat(e.target.value) })} /> diff --git a/examples/search_explorer/public/demo_strategy.tsx b/examples/search_explorer/public/demo_strategy.tsx index 7c6c21d2b7aedb..3de6827818e14b 100644 --- a/examples/search_explorer/public/demo_strategy.tsx +++ b/examples/search_explorer/public/demo_strategy.tsx @@ -81,7 +81,7 @@ export class DemoStrategy extends React.Component { this.setState({ name: e.target.value })} + onChange={(e) => this.setState({ name: e.target.value })} /> @@ -90,7 +90,7 @@ export class DemoStrategy extends React.Component { this.setState({ mood: e.target.value })} + onChange={(e) => this.setState({ mood: e.target.value })} /> diff --git a/examples/search_explorer/public/do_search.tsx b/examples/search_explorer/public/do_search.tsx index a6b6b9b57db4a9..deadb06b16f5fd 100644 --- a/examples/search_explorer/public/do_search.tsx +++ b/examples/search_explorer/public/do_search.tsx @@ -61,10 +61,10 @@ export class DoSearch extends React.Component { this.abortController = new AbortController(); this.props.search(this.abortController.signal).subscribe( - response => { + (response) => { this.setState({ response, error: undefined }); }, - error => { + (error) => { this.setState({ error, searching: false, response: undefined }); }, () => { diff --git a/examples/search_explorer/public/es_strategy.tsx b/examples/search_explorer/public/es_strategy.tsx index aaf9dada903410..bc6223c478bf58 100644 --- a/examples/search_explorer/public/es_strategy.tsx +++ b/examples/search_explorer/public/es_strategy.tsx @@ -92,7 +92,7 @@ export class EsSearchTest extends React.Component { this.setState({ index: e.target.value, changes: true })} + onChange={(e) => this.setState({ index: e.target.value, changes: true })} /> @@ -101,7 +101,7 @@ export class EsSearchTest extends React.Component { this.setState({ query: e.target.value, changes: true })} + onChange={(e) => this.setState({ query: e.target.value, changes: true })} /> diff --git a/examples/search_explorer/public/guide_section.tsx b/examples/search_explorer/public/guide_section.tsx index 1562e33b14c2f5..c13c11dc5864cf 100644 --- a/examples/search_explorer/public/guide_section.tsx +++ b/examples/search_explorer/public/guide_section.tsx @@ -59,7 +59,7 @@ export class GuideSection extends React.Component { } if (props.codeSections) { - props.codeSections.forEach(section => { + props.codeSections.forEach((section) => { this.tabs.push({ name: section.title, displayName: section.title, @@ -79,7 +79,7 @@ export class GuideSection extends React.Component { }; renderTabs() { - return this.tabs.map(tab => ( + return this.tabs.map((tab) => ( this.onSelectedTabChanged(tab.name)} isSelected={tab.name === this.state.selectedTab} @@ -98,7 +98,7 @@ export class GuideSection extends React.Component { if (!this.props.codeSections) { return undefined; } - const section = this.props.codeSections.find(s => s.title === this.state.selectedTab); + const section = this.props.codeSections.find((s) => s.title === this.state.selectedTab); if (!section) { throw new Error('No section named ' + this.state.selectedTab); diff --git a/examples/state_containers_examples/kibana.json b/examples/state_containers_examples/kibana.json index 437e9a4fac63c2..581b399e3ffbac 100644 --- a/examples/state_containers_examples/kibana.json +++ b/examples/state_containers_examples/kibana.json @@ -2,7 +2,6 @@ "id": "stateContainersExamples", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["state_containers_examples"], "server": true, "ui": true, "requiredPlugins": ["navigation", "data"], diff --git a/examples/state_containers_examples/package.json b/examples/state_containers_examples/package.json deleted file mode 100644 index b309494a366628..00000000000000 --- a/examples/state_containers_examples/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "state_containers_examples", - "version": "1.0.0", - "main": "target/examples/state_containers_examples", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/state_containers_examples/public/todo/todo.tsx b/examples/state_containers_examples/public/todo/todo.tsx index 597c2b19be0f60..b6f4f6550026be 100644 --- a/examples/state_containers_examples/public/todo/todo.tsx +++ b/examples/state_containers_examples/public/todo/todo.tsx @@ -61,7 +61,7 @@ const defaultGlobalState: GlobalState = { text: '' }; const globalStateContainer = createStateContainer( defaultGlobalState, { - setText: state => text => ({ ...state, text }), + setText: (state) => (text) => ({ ...state, text }), } ); @@ -81,7 +81,7 @@ const TodoApp: React.FC = ({ filter }) => { const { text } = GlobalStateHelpers.useState(); const { edit: editTodo, delete: deleteTodo, add: addTodo } = useTransitions(); const todos = useState().todos; - const filteredTodos = todos.filter(todo => { + const filteredTodos = todos.filter((todo) => { if (!filter) return true; if (filter === 'completed') return todo.completed; if (filter === 'not-completed') return !todo.completed; @@ -111,13 +111,13 @@ const TodoApp: React.FC = ({ filter }) => {
    - {filteredTodos.map(todo => ( + {filteredTodos.map((todo) => (
  • { + onChange={(e) => { editTodo({ ...todo, completed: e.target.checked, @@ -139,7 +139,7 @@ const TodoApp: React.FC = ({ filter }) => { ))}
{ + onSubmit={(e) => { const inputRef = (e.target as HTMLFormElement).elements.namedItem( 'newTodo' ) as HTMLInputElement; @@ -147,7 +147,7 @@ const TodoApp: React.FC = ({ filter }) => { addTodo({ text: inputRef.value, completed: false, - id: todos.map(todo => todo.id).reduce((a, b) => Math.max(a, b), 0) + 1, + id: todos.map((todo) => todo.id).reduce((a, b) => Math.max(a, b), 0) + 1, }); inputRef.value = ''; e.preventDefault(); @@ -157,7 +157,7 @@ const TodoApp: React.FC = ({ filter }) => {
- setText(e.target.value)} /> + setText(e.target.value)} />
); @@ -173,7 +173,7 @@ export const TodoAppPage: React.FC<{ appTitle: string; appBasePath: string; isInitialRoute: () => boolean; -}> = props => { +}> = (props) => { const initialAppUrl = React.useRef(window.location.href); const [useHashedUrl, setUseHashedUrl] = React.useState(false); @@ -181,7 +181,7 @@ export const TodoAppPage: React.FC<{ * Replicates what src/legacy/ui/public/chrome/api/nav.ts did * Persists the url in sessionStorage and tries to restore it on "componentDidMount" */ - useUrlTracker(`lastUrlTracker:${props.appInstanceId}`, props.history, urlToRestore => { + useUrlTracker(`lastUrlTracker:${props.appInstanceId}`, props.history, (urlToRestore) => { // shouldRestoreUrl: // App decides if it should restore url or not // In this specific case, restore only if navigated to initial route diff --git a/examples/state_containers_examples/public/with_data_services/components/app.tsx b/examples/state_containers_examples/public/with_data_services/components/app.tsx index c820929d8a61da..baf627fd62a32b 100644 --- a/examples/state_containers_examples/public/with_data_services/components/app.tsx +++ b/examples/state_containers_examples/public/with_data_services/components/app.tsx @@ -135,7 +135,7 @@ const App = ({ appStateContainer.set({ ...appState, name: e.target.value })} + onChange={(e) => appStateContainer.set({ ...appState, name: e.target.value })} aria-label="My name" /> @@ -217,7 +217,7 @@ function useAppStateSyncing( stateContainer: { ...appStateContainer, // stateSync utils requires explicit handling of default state ("null") - set: state => state && appStateContainer.set(state), + set: (state) => state && appStateContainer.set(state), }, }); diff --git a/examples/ui_action_examples/kibana.json b/examples/ui_action_examples/kibana.json index d5c3f0f2ec33a9..cd12442daf61c0 100644 --- a/examples/ui_action_examples/kibana.json +++ b/examples/ui_action_examples/kibana.json @@ -2,7 +2,6 @@ "id": "uiActionsExamples", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["ui_actions_examples"], "server": false, "ui": true, "requiredPlugins": ["uiActions"], diff --git a/examples/ui_action_examples/package.json b/examples/ui_action_examples/package.json deleted file mode 100644 index fbede6b4dbad7d..00000000000000 --- a/examples/ui_action_examples/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "ui_actions_examples", - "version": "1.0.0", - "main": "target/examples/ui_actions_examples", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/ui_actions_explorer/kibana.json b/examples/ui_actions_explorer/kibana.json index 126e79eb35757e..e88739a9e44d6c 100644 --- a/examples/ui_actions_explorer/kibana.json +++ b/examples/ui_actions_explorer/kibana.json @@ -2,7 +2,6 @@ "id": "uiActionsExplorer", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["ui_actions_explorer"], "server": false, "ui": true, "requiredPlugins": ["uiActions", "uiActionsExamples"], diff --git a/examples/ui_actions_explorer/package.json b/examples/ui_actions_explorer/package.json deleted file mode 100644 index 1758471ced483a..00000000000000 --- a/examples/ui_actions_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "ui_actions_explorer", - "version": "1.0.0", - "main": "target/examples/ui_actions_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/ui_actions_explorer/public/actions/actions.tsx b/examples/ui_actions_explorer/public/actions/actions.tsx index 64a820ab6d1947..4ef8d5bf4d9c66 100644 --- a/examples/ui_actions_explorer/public/actions/actions.tsx +++ b/examples/ui_actions_explorer/public/actions/actions.tsx @@ -47,14 +47,14 @@ export interface PhoneContext { export const makePhoneCallAction = createAction({ type: ACTION_CALL_PHONE_NUMBER, getDisplayName: () => 'Call phone number', - execute: async context => alert(`Pretend calling ${context.phone}...`), + execute: async (context) => alert(`Pretend calling ${context.phone}...`), }); export const lookUpWeatherAction = createAction({ type: ACTION_TRAVEL_GUIDE, getIconType: () => 'popout', getDisplayName: () => 'View travel guide', - execute: async context => { + execute: async (context) => { window.open(`https://www.worldtravelguide.net/?s=${context.country}`, '_blank'); }, }); @@ -67,7 +67,7 @@ export const viewInMapsAction = createAction({ type: ACTION_VIEW_IN_MAPS, getIconType: () => 'popout', getDisplayName: () => 'View in maps', - execute: async context => { + execute: async (context) => { window.open(`https://www.google.com/maps/place/${context.country}`, '_blank'); }, }); @@ -90,7 +90,7 @@ function EditUserModal({ const [name, setName] = useState(user.name); return ( - setName(e.target.value)} /> + setName(e.target.value)} /> { update({ ...user, name }); diff --git a/examples/ui_actions_explorer/public/app.tsx b/examples/ui_actions_explorer/public/app.tsx index f08b8bb29bdd35..1b0667962a3c2f 100644 --- a/examples/ui_actions_explorer/public/app.tsx +++ b/examples/ui_actions_explorer/public/app.tsx @@ -72,7 +72,7 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => { from. Using the UI Action and Trigger API makes your plugin extensible by other plugins. Any actions attached to the `HELLO_WORLD_TRIGGER_ID` will show up here!

- setName(e.target.value)} /> + setName(e.target.value)} /> { diff --git a/examples/ui_actions_explorer/public/trigger_context_example.tsx b/examples/ui_actions_explorer/public/trigger_context_example.tsx index 4b886521039663..05a9895d3fac4c 100644 --- a/examples/ui_actions_explorer/public/trigger_context_example.tsx +++ b/examples/ui_actions_explorer/public/trigger_context_example.tsx @@ -105,7 +105,7 @@ export function TriggerContextExample({ uiActionsApi }: Props) { ]; const updateUser = (newUser: User, oldName: string) => { - const index = rows.findIndex(u => u.name === oldName); + const index = rows.findIndex((u) => u.name === oldName); const newRows = [...rows]; newRows.splice(index, 1, createRowData(newUser, uiActionsApi, updateUser)); setRows(newRows); diff --git a/examples/url_generators_examples/kibana.json b/examples/url_generators_examples/kibana.json index 0767018e3bb981..cdb2127fdd26f5 100644 --- a/examples/url_generators_examples/kibana.json +++ b/examples/url_generators_examples/kibana.json @@ -2,7 +2,6 @@ "id": "urlGeneratorsExamples", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["url_generators_examples"], "server": false, "ui": true, "requiredPlugins": ["share"], diff --git a/examples/url_generators_examples/package.json b/examples/url_generators_examples/package.json deleted file mode 100644 index d3e8bd98aebf4c..00000000000000 --- a/examples/url_generators_examples/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "url_generators_examples", - "version": "1.0.0", - "main": "target/examples/url_generators_examples", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/url_generators_examples/public/app.tsx b/examples/url_generators_examples/public/app.tsx index c39cd876ea9b15..82f36fa13ea71d 100644 --- a/examples/url_generators_examples/public/app.tsx +++ b/examples/url_generators_examples/public/app.tsx @@ -67,7 +67,7 @@ export const Routes: React.FC<{}> = () => { export const LinksExample: React.FC<{ appBasePath: string; -}> = props => { +}> = (props) => { const history = React.useMemo( () => createBrowserHistory({ diff --git a/examples/url_generators_examples/public/url_generator.ts b/examples/url_generators_examples/public/url_generator.ts index f21b1c9295e660..c74ade8bf743d0 100644 --- a/examples/url_generators_examples/public/url_generator.ts +++ b/examples/url_generators_examples/public/url_generator.ts @@ -38,7 +38,7 @@ export const createHelloPageLinkGenerator = ( getStartServices: () => Promise<{ appBasePath: string }> ): UrlGeneratorsDefinition => ({ id: HELLO_URL_GENERATOR, - createUrl: async state => { + createUrl: async (state) => { const startServices = await getStartServices(); const appBasePath = startServices.appBasePath; const parsedUrl = url.parse(window.location.href); @@ -72,7 +72,7 @@ export type LegacyHelloLinkGeneratorState = UrlGeneratorState< export const helloPageLinkGeneratorV1: UrlGeneratorsDefinition = { id: HELLO_URL_GENERATOR_V1, isDeprecated: true, - migrate: async state => { + migrate: async (state) => { return { id: HELLO_URL_GENERATOR, state: { firstName: state.name, lastName: '' } }; }, }; diff --git a/examples/url_generators_explorer/kibana.json b/examples/url_generators_explorer/kibana.json index 94ab75b3388898..fe514859bf3d55 100644 --- a/examples/url_generators_explorer/kibana.json +++ b/examples/url_generators_explorer/kibana.json @@ -2,7 +2,6 @@ "id": "urlGeneratorsExplorer", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["url_generators_explorer"], "server": false, "ui": true, "requiredPlugins": ["share", "urlGeneratorsExamples"], diff --git a/examples/url_generators_explorer/package.json b/examples/url_generators_explorer/package.json deleted file mode 100644 index f472ba1d08506a..00000000000000 --- a/examples/url_generators_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "url_generators_explorer", - "version": "1.0.0", - "main": "target/examples/url_generators_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/examples/url_generators_explorer/public/app.tsx b/examples/url_generators_explorer/public/app.tsx index 77e804ae08c5f4..50dd2e075c5280 100644 --- a/examples/url_generators_explorer/public/app.tsx +++ b/examples/url_generators_explorer/public/app.tsx @@ -81,7 +81,7 @@ const ActionsExplorer = ({ getLinkGenerator }: Props) => { const updateLinks = async () => { const updatedLinks = await Promise.all( - persistedLinks.map(async savedLink => { + persistedLinks.map(async (savedLink) => { const generator = getLinkGenerator(savedLink.id); const link = await generator.createUrl(savedLink.state); return { @@ -109,11 +109,11 @@ const ActionsExplorer = ({ getLinkGenerator }: Props) => { { + onChange={(e) => { setFirstName(e.target.value); }} /> - setLastName(e.target.value)} /> + setLastName(e.target.value)} /> setPersistedLinks([ @@ -142,7 +142,7 @@ const ActionsExplorer = ({ getLinkGenerator }: Props) => { {buildingLinks ? (
loading...
) : ( - migratedLinks.map(link => ( + migratedLinks.map((link) => ( dateMath.parse('now', { forceNow: '2000-01-01T00:00:00.000Z' }); expect(fn).to.throwError(); }); - it('should throw an Error if passed a moment', function() { + it('should throw an Error if passed a moment', function () { expect(() => dateMath.parse('now', { forceNow: moment() })).to.throwError(); }); - it('should throw an Error if passed an invalid date', function() { + it('should throw an Error if passed an invalid date', function () { expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).to.throwError(); }); }); }); - describe('objects and strings', function() { + describe('objects and strings', function () { let mmnt; let date; let string; let now; - beforeEach(function() { + beforeEach(function () { clock = sinon.useFakeTimers(unix); now = moment(); mmnt = moment(anchor); @@ -99,61 +99,61 @@ describe('dateMath', function() { string = mmnt.format(format); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - it('should return the same moment if passed a moment', function() { + it('should return the same moment if passed a moment', function () { expect(dateMath.parse(mmnt)).to.eql(mmnt); }); - it('should return a moment if passed a date', function() { + it('should return a moment if passed a date', function () { expect(dateMath.parse(date).format(format)).to.eql(mmnt.format(format)); }); - it('should return a moment if passed an ISO8601 string', function() { + it('should return a moment if passed an ISO8601 string', function () { expect(dateMath.parse(string).format(format)).to.eql(mmnt.format(format)); }); - it('should return the current time when parsing now', function() { + it('should return the current time when parsing now', function () { expect(dateMath.parse('now').format(format)).to.eql(now.format(format)); }); - it('should use the forceNow parameter when parsing now', function() { + it('should use the forceNow parameter when parsing now', function () { expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).to.eql(unix); }); }); - describe('subtraction', function() { + describe('subtraction', function () { let now; let anchored; - beforeEach(function() { + beforeEach(function () { clock = sinon.useFakeTimers(unix); now = moment(); anchored = moment(anchor); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - [5, 12, 247].forEach(len => { - spans.forEach(span => { + [5, 12, 247].forEach((len) => { + spans.forEach((span) => { const nowEx = `now-${len}${span}`; const thenEx = `${anchor}||-${len}${span}`; - it('should return ' + len + span + ' ago', function() { + it('should return ' + len + span + ' ago', function () { const parsed = dateMath.parse(nowEx).format(format); expect(parsed).to.eql(now.subtract(len, span).format(format)); }); - it('should return ' + len + span + ' before ' + anchor, function() { + it('should return ' + len + span + ' before ' + anchor, function () { const parsed = dateMath.parse(thenEx).format(format); expect(parsed).to.eql(anchored.subtract(len, span).format(format)); }); - it('should return ' + len + span + ' before forceNow', function() { + it('should return ' + len + span + ' before forceNow', function () { const parsed = dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf(); expect(parsed).to.eql(anchored.subtract(len, span).valueOf()); }); @@ -161,36 +161,36 @@ describe('dateMath', function() { }); }); - describe('addition', function() { + describe('addition', function () { let now; let anchored; - beforeEach(function() { + beforeEach(function () { clock = sinon.useFakeTimers(unix); now = moment(); anchored = moment(anchor); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - [5, 12, 247].forEach(len => { - spans.forEach(span => { + [5, 12, 247].forEach((len) => { + spans.forEach((span) => { const nowEx = `now+${len}${span}`; const thenEx = `${anchor}||+${len}${span}`; - it('should return ' + len + span + ' from now', function() { + it('should return ' + len + span + ' from now', function () { expect(dateMath.parse(nowEx).format(format)).to.eql(now.add(len, span).format(format)); }); - it('should return ' + len + span + ' after ' + anchor, function() { + it('should return ' + len + span + ' after ' + anchor, function () { expect(dateMath.parse(thenEx).format(format)).to.eql( anchored.add(len, span).format(format) ); }); - it('should return ' + len + span + ' after forceNow', function() { + it('should return ' + len + span + ' after forceNow', function () { expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).to.eql( anchored.add(len, span).valueOf() ); @@ -199,40 +199,40 @@ describe('dateMath', function() { }); }); - describe('rounding', function() { + describe('rounding', function () { let now; let anchored; - beforeEach(function() { + beforeEach(function () { clock = sinon.useFakeTimers(unix); now = moment(); anchored = moment(anchor); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - spans.forEach(span => { - it(`should round now to the beginning of the ${span}`, function() { + spans.forEach((span) => { + it(`should round now to the beginning of the ${span}`, function () { expect(dateMath.parse('now/' + span).format(format)).to.eql( now.startOf(span).format(format) ); }); - it(`should round now to the beginning of forceNow's ${span}`, function() { + it(`should round now to the beginning of forceNow's ${span}`, function () { expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).to.eql( anchored.startOf(span).valueOf() ); }); - it(`should round now to the end of the ${span}`, function() { + it(`should round now to the end of the ${span}`, function () { expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).to.eql( now.endOf(span).format(format) ); }); - it(`should round now to the end of forceNow's ${span}`, function() { + it(`should round now to the end of forceNow's ${span}`, function () { expect( dateMath.parse('now/' + span, { roundUp: true, forceNow: anchoredDate }).valueOf() ).to.eql(anchored.endOf(span).valueOf()); @@ -240,61 +240,46 @@ describe('dateMath', function() { }); }); - describe('math and rounding', function() { + describe('math and rounding', function () { let now; let anchored; - beforeEach(function() { + beforeEach(function () { clock = sinon.useFakeTimers(unix); now = moment(); anchored = moment(anchor); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - it('should round to the nearest second with 0 value', function() { + it('should round to the nearest second with 0 value', function () { const val = dateMath.parse('now-0s/s').format(format); expect(val).to.eql(now.startOf('s').format(format)); }); - it('should subtract 17s, rounded to the nearest second', function() { + it('should subtract 17s, rounded to the nearest second', function () { const val = dateMath.parse('now-17s/s').format(format); - expect(val).to.eql( - now - .startOf('s') - .subtract(17, 's') - .format(format) - ); + expect(val).to.eql(now.startOf('s').subtract(17, 's').format(format)); }); - it('should add 555ms, rounded to the nearest millisecond', function() { + it('should add 555ms, rounded to the nearest millisecond', function () { const val = dateMath.parse('now+555ms/ms').format(format); - expect(val).to.eql( - now - .add(555, 'ms') - .startOf('ms') - .format(format) - ); + expect(val).to.eql(now.add(555, 'ms').startOf('ms').format(format)); }); - it('should subtract 555ms, rounded to the nearest second', function() { + it('should subtract 555ms, rounded to the nearest second', function () { const val = dateMath.parse('now-555ms/s').format(format); - expect(val).to.eql( - now - .subtract(555, 'ms') - .startOf('s') - .format(format) - ); + expect(val).to.eql(now.subtract(555, 'ms').startOf('s').format(format)); }); - it('should round weeks to Sunday by default', function() { + it('should round weeks to Sunday by default', function () { const val = dateMath.parse('now-1w/w'); expect(val.isoWeekday()).to.eql(7); }); - it('should round weeks based on the passed moment locale start of week setting', function() { + it('should round weeks based on the passed moment locale start of week setting', function () { const m = momentClone(); // Define a locale, that has Tuesday as beginning of the week m.defineLocale('x-test', { @@ -304,7 +289,7 @@ describe('dateMath', function() { expect(val.isoWeekday()).to.eql(2); }); - it('should round up weeks based on the passed moment locale start of week setting', function() { + it('should round up weeks based on the passed moment locale start of week setting', function () { const m = momentClone(); // Define a locale, that has Tuesday as beginning of the week m.defineLocale('x-test', { @@ -319,7 +304,7 @@ describe('dateMath', function() { expect(val.isoWeekday()).to.eql(3 - 1); }); - it('should round relative to forceNow', function() { + it('should round relative to forceNow', function () { const val = dateMath.parse('now-0s/s', { forceNow: anchoredDate }).valueOf(); expect(val).to.eql(anchored.startOf('s').valueOf()); }); @@ -329,15 +314,15 @@ describe('dateMath', function() { }); }); - describe('used momentjs instance', function() { - it('should use the default moment instance if parameter not specified', function() { + describe('used momentjs instance', function () { + it('should use the default moment instance if parameter not specified', function () { const momentSpy = sinon.spy(moment, 'isMoment'); dateMath.parse('now'); expect(momentSpy.called).to.be(true); momentSpy.restore(); }); - it('should not use default moment instance if parameter is specified', function() { + it('should not use default moment instance if parameter is specified', function () { const m = momentClone(); const momentSpy = sinon.spy(moment, 'isMoment'); const cloneSpy = sinon.spy(m, 'isMoment'); @@ -348,7 +333,7 @@ describe('dateMath', function() { cloneSpy.restore(); }); - it('should work with multiple different instances', function() { + it('should work with multiple different instances', function () { const m1 = momentClone(); const m2 = momentClone(); const m1Spy = sinon.spy(m1, 'isMoment'); @@ -365,7 +350,7 @@ describe('dateMath', function() { m2Spy.restore(); }); - it('should use global instance after passing an instance', function() { + it('should use global instance after passing an instance', function () { const m = momentClone(); const momentSpy = sinon.spy(moment, 'isMoment'); const cloneSpy = sinon.spy(m, 'isMoment'); @@ -382,12 +367,12 @@ describe('dateMath', function() { }); }); - describe('units', function() { - it('should have units descending for unitsDesc', function() { + describe('units', function () { + it('should have units descending for unitsDesc', function () { expect(dateMath.unitsDesc).to.eql(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); }); - it('should have units ascending for unitsAsc', function() { + it('should have units ascending for unitsAsc', function () { expect(dateMath.unitsAsc).to.eql(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); }); }); diff --git a/packages/elastic-datemath/src/index.js b/packages/elastic-datemath/src/index.js index afedad3ef6f72a..52ce12ddf70279 100644 --- a/packages/elastic-datemath/src/index.js +++ b/packages/elastic-datemath/src/index.js @@ -34,9 +34,9 @@ const units = Object.keys(unitsMap).sort((a, b) => unitsMap[b].weight - unitsMap const unitsDesc = [...units]; const unitsAsc = [...units].reverse(); -const isDate = d => Object.prototype.toString.call(d) === '[object Date]'; +const isDate = (d) => Object.prototype.toString.call(d) === '[object Date]'; -const isValidDate = d => isDate(d) && !isNaN(d.valueOf()); +const isValidDate = (d) => isDate(d) && !isNaN(d.valueOf()); /* * This is a simplified version of elasticsearch's date parser. diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index 34b1b0fec376f6..d9aef63c0115c9 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -15,8 +15,8 @@ }, "homepage": "https://github.com/elastic/eslint-config-kibana#readme", "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^2.15.0", - "@typescript-eslint/parser": "^2.15.0", + "@typescript-eslint/eslint-plugin": "^2.33.0", + "@typescript-eslint/parser": "^2.33.0", "babel-eslint": "^10.0.3", "eslint": "^6.8.0", "eslint-plugin-babel": "^5.3.0", diff --git a/packages/kbn-analytics/scripts/build.js b/packages/kbn-analytics/scripts/build.js index bb28c1460c9c23..448d1ca9332f24 100644 --- a/packages/kbn-analytics/scripts/build.js +++ b/packages/kbn-analytics/scripts/build.js @@ -31,7 +31,7 @@ const padRight = (width, str) => run( async ({ log, flags }) => { - await withProcRunner(log, async proc => { + await withProcRunner(log, async (proc) => { log.info('Deleting old output'); await del(BUILD_DIR); @@ -43,7 +43,7 @@ run( log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`); await Promise.all([ - ...['web', 'node'].map(subTask => + ...['web', 'node'].map((subTask) => proc.run(padRight(10, `babel:${subTask}`), { cmd: 'babel', args: [ diff --git a/packages/kbn-analytics/src/report.ts b/packages/kbn-analytics/src/report.ts index 58891e48aa3a63..d9303d2d3af1d3 100644 --- a/packages/kbn-analytics/src/report.ts +++ b/packages/kbn-analytics/src/report.ts @@ -86,7 +86,7 @@ export class ReportManager { }; } assignReports(newMetrics: Metric | Metric[]) { - wrapArray(newMetrics).forEach(newMetric => this.assignReport(this.report, newMetric)); + wrapArray(newMetrics).forEach((newMetric) => this.assignReport(this.report, newMetric)); return { report: this.report }; } static createMetricKey(metric: Metric): string { diff --git a/packages/kbn-analytics/src/reporter.ts b/packages/kbn-analytics/src/reporter.ts index cbcdf6af63052b..b20ddc0e58ba7c 100644 --- a/packages/kbn-analytics/src/reporter.ts +++ b/packages/kbn-analytics/src/reporter.ts @@ -115,7 +115,7 @@ export class Reporter { eventNames: string | string[], count?: number ) => { - const metrics = wrapArray(eventNames).map(eventName => { + const metrics = wrapArray(eventNames).map((eventName) => { this.log(`${type} Metric -> (${appName}:${eventName}):`); const report = createUiStatsMetric({ type, appName, eventName, count }); this.log(report); diff --git a/packages/kbn-babel-code-parser/src/code_parser.js b/packages/kbn-babel-code-parser/src/code_parser.js index 9431eb639e2e5a..91927780363ac8 100644 --- a/packages/kbn-babel-code-parser/src/code_parser.js +++ b/packages/kbn-babel-code-parser/src/code_parser.js @@ -79,7 +79,7 @@ export async function parseEntries(cwd, entries, strategy, results, wasParsed = const sanitizedCwd = cwd || process.cwd(); // Test each entry against canRequire function - const entriesQueue = entries.map(entry => canRequire(entry)); + const entriesQueue = entries.map((entry) => canRequire(entry)); while (entriesQueue.length) { // Get the first element in the queue as diff --git a/packages/kbn-babel-code-parser/src/strategies.js b/packages/kbn-babel-code-parser/src/strategies.js index f116abde9e0e6d..2369692ad434b1 100644 --- a/packages/kbn-babel-code-parser/src/strategies.js +++ b/packages/kbn-babel-code-parser/src/strategies.js @@ -59,7 +59,7 @@ export async function dependenciesParseStrategy( // Get dependencies from a single file and filter // out node native modules from the result const dependencies = (await parseSingleFile(mainEntry, dependenciesVisitorsGenerator)).filter( - dep => !builtinModules.includes(dep) + (dep) => !builtinModules.includes(dep) ); // Return the list of all the new entries found into diff --git a/packages/kbn-babel-code-parser/src/strategies.test.js b/packages/kbn-babel-code-parser/src/strategies.test.js index dc2c599e81c397..e61c784cdcd541 100644 --- a/packages/kbn-babel-code-parser/src/strategies.test.js +++ b/packages/kbn-babel-code-parser/src/strategies.test.js @@ -84,7 +84,7 @@ describe('Code Parser Strategies', () => { cb(null, `require('./relative_dep')`); }); - canRequire.mockImplementation(entry => { + canRequire.mockImplementation((entry) => { if (entry === `${mockCwd}dep1/relative_dep`) { return `${entry}/index.js`; } diff --git a/packages/kbn-babel-code-parser/src/visitors.js b/packages/kbn-babel-code-parser/src/visitors.js index 30014941d2a272..b159848d424fa5 100644 --- a/packages/kbn-babel-code-parser/src/visitors.js +++ b/packages/kbn-babel-code-parser/src/visitors.js @@ -21,7 +21,7 @@ export function dependenciesVisitorsGenerator(dependenciesAcc) { // raw values on require + require.resolve CallExpression: ({ node }) => { // AST check for require expressions - const isRequire = node => { + const isRequire = (node) => { return matches({ callee: { type: 'Identifier', @@ -31,7 +31,7 @@ export function dependenciesVisitorsGenerator(dependenciesAcc) { }; // AST check for require.resolve expressions - const isRequireResolve = node => { + const isRequireResolve = (node) => { return matches({ callee: { type: 'MemberExpression', @@ -66,7 +66,7 @@ export function dependenciesVisitorsGenerator(dependenciesAcc) { // raw values on import ImportDeclaration: ({ node }) => { // AST check for supported import expressions - const isImport = node => { + const isImport = (node) => { return matches({ type: 'ImportDeclaration', source: { @@ -85,7 +85,7 @@ export function dependenciesVisitorsGenerator(dependenciesAcc) { // raw values on export from ExportNamedDeclaration: ({ node }) => { // AST check for supported export from expressions - const isExportFrom = node => { + const isExportFrom = (node) => { return matches({ type: 'ExportNamedDeclaration', source: { @@ -104,7 +104,7 @@ export function dependenciesVisitorsGenerator(dependenciesAcc) { // raw values on export * from ExportAllDeclaration: ({ node }) => { // AST check for supported export * from expressions - const isExportAllFrom = node => { + const isExportAllFrom = (node) => { return matches({ type: 'ExportAllDeclaration', source: { diff --git a/packages/kbn-babel-code-parser/src/visitors.test.js b/packages/kbn-babel-code-parser/src/visitors.test.js index 6a29d144a4dee9..d2704fa9dfb721 100644 --- a/packages/kbn-babel-code-parser/src/visitors.test.js +++ b/packages/kbn-babel-code-parser/src/visitors.test.js @@ -21,7 +21,7 @@ import * as parser from '@babel/parser'; import traverse from '@babel/traverse'; import { dependenciesVisitorsGenerator } from './visitors'; -const visitorsApplier = code => { +const visitorsApplier = (code) => { const result = []; traverse( parser.parse(code, { diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 1a2f6941c20200..ab0d875430d017 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -7,14 +7,12 @@ "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-proposal-optional-chaining": "^7.9.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-modules-commonjs": "^7.9.0", "@babel/preset-env": "^7.9.0", "@babel/preset-react": "^7.9.1", "@babel/preset-typescript": "^7.9.0", "babel-plugin-add-module-exports": "^1.0.2", "babel-plugin-filter-imports": "^3.0.0", - "babel-plugin-styled-components": "^1.10.6", + "babel-plugin-styled-components": "^1.10.7", "babel-plugin-transform-define": "^1.3.1", "babel-plugin-transform-imports": "^2.0.0" } diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 2c1129f275bfe3..97462a579e3c46 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -33,8 +33,6 @@ module.exports = () => { require('./common_preset'), ], plugins: [ - require.resolve('@babel/plugin-transform-modules-commonjs'), - require.resolve('@babel/plugin-syntax-dynamic-import'), [ require.resolve('babel-plugin-styled-components'), { diff --git a/packages/kbn-config-schema/src/errors/schema_error.test.ts b/packages/kbn-config-schema/src/errors/schema_error.test.ts index 0f632b781e9a60..d5cbb5a718a6a3 100644 --- a/packages/kbn-config-schema/src/errors/schema_error.test.ts +++ b/packages/kbn-config-schema/src/errors/schema_error.test.ts @@ -26,8 +26,8 @@ import { SchemaError } from '.'; export const cleanStack = (stack: string) => stack .split('\n') - .filter(line => !line.includes('node_modules/') && !line.includes('internal/')) - .map(line => { + .filter((line) => !line.includes('node_modules/') && !line.includes('internal/')) + .map((line) => { const parts = /.*\((.*)\).?/.exec(line) || []; if (parts.length === 0) { diff --git a/packages/kbn-config-schema/src/errors/validation_error.ts b/packages/kbn-config-schema/src/errors/validation_error.ts index 2a4f887bc43498..0c86b61ba1e2ac 100644 --- a/packages/kbn-config-schema/src/errors/validation_error.ts +++ b/packages/kbn-config-schema/src/errors/validation_error.ts @@ -26,12 +26,12 @@ export class ValidationError extends SchemaError { let message = error.message; if (error instanceof SchemaTypesError) { const indentLevel = level || 0; - const childErrorMessages = error.errors.map(childError => + const childErrorMessages = error.errors.map((childError) => ValidationError.extractMessage(childError, namespace, indentLevel + 1) ); message = `${message}\n${childErrorMessages - .map(childErrorMessage => `${' '.repeat(indentLevel)}- ${childErrorMessage}`) + .map((childErrorMessage) => `${' '.repeat(indentLevel)}- ${childErrorMessage}`) .join('\n')}`; } diff --git a/packages/kbn-config-schema/src/internals/index.ts b/packages/kbn-config-schema/src/internals/index.ts index f84e14d2f741db..f3756aaf90793e 100644 --- a/packages/kbn-config-schema/src/internals/index.ts +++ b/packages/kbn-config-schema/src/internals/index.ts @@ -42,9 +42,7 @@ function isMap(o: any): o is Map { const anyCustomRule: Rules = { name: 'custom', params: { - validator: Joi.func() - .maxArity(1) - .required(), + validator: Joi.func().maxArity(1).required(), }, validate(params, value, state, options) { let validationResultMessage; diff --git a/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts index e0ef3835ca0a37..485251055d2b83 100644 --- a/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts +++ b/packages/kbn-config-schema/src/typeguards/is_config_schema.test.ts @@ -47,7 +47,7 @@ describe('isConfigSchema', () => { expect(isConfigSchema(undefined)).toBe(false); expect(isConfigSchema([1, 2, 3])).toBe(false); expect(isConfigSchema({ foo: 'bar' })).toBe(false); - expect(isConfigSchema(function() {})).toBe(false); + expect(isConfigSchema(function () {})).toBe(false); }); it('returns true as long as `__isKbnConfigSchemaType` is true', () => { diff --git a/packages/kbn-config-schema/src/types/array_type.ts b/packages/kbn-config-schema/src/types/array_type.ts index 0df0d44a37951f..2fe1fa24222a12 100644 --- a/packages/kbn-config-schema/src/types/array_type.ts +++ b/packages/kbn-config-schema/src/types/array_type.ts @@ -28,10 +28,7 @@ export type ArrayOptions = TypeOptions & { export class ArrayType extends Type { constructor(type: Type, options: ArrayOptions = {}) { - let schema = internals - .array() - .items(type.getSchema().optional()) - .sparse(false); + let schema = internals.array().items(type.getSchema().optional()).sparse(false); if (options.minSize !== undefined) { schema = schema.min(options.minSize); diff --git a/packages/kbn-config-schema/src/types/string_type.ts b/packages/kbn-config-schema/src/types/string_type.ts index 7f49440b8d7e29..cb780bcbbc6bde 100644 --- a/packages/kbn-config-schema/src/types/string_type.ts +++ b/packages/kbn-config-schema/src/types/string_type.ts @@ -36,14 +36,14 @@ export class StringType extends Type { let schema = options.hostname === true ? internals.string().hostname() - : internals.any().custom(value => { + : internals.any().custom((value) => { if (typeof value !== 'string') { return `expected value of type [string] but got [${typeDetect(value)}]`; } }); if (options.minLength !== undefined) { - schema = schema.custom(value => { + schema = schema.custom((value) => { if (value.length < options.minLength!) { return `value has length [${value.length}] but it must have a minimum length of [${options.minLength}].`; } @@ -51,7 +51,7 @@ export class StringType extends Type { } if (options.maxLength !== undefined) { - schema = schema.custom(value => { + schema = schema.custom((value) => { if (value.length > options.maxLength!) { return `value has length [${value.length}] but it must have a maximum length of [${options.maxLength}].`; } diff --git a/packages/kbn-config-schema/src/types/union_type.ts b/packages/kbn-config-schema/src/types/union_type.ts index f4de829204e80b..80fa8443e75d00 100644 --- a/packages/kbn-config-schema/src/types/union_type.ts +++ b/packages/kbn-config-schema/src/types/union_type.ts @@ -24,7 +24,7 @@ import { Type, TypeOptions } from './type'; export class UnionType>, T> extends Type { constructor(types: RTS, options?: TypeOptions) { - const schema = internals.alternatives(types.map(type => type.getSchema())); + const schema = internals.alternatives(types.map((type) => type.getSchema())); super(schema, options); } diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts index 4e912896104328..b38a27fdc1b485 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts @@ -145,7 +145,7 @@ export class CiStatsReporter { `failed to reach kibana-ci-stats service [reason=${reason}], retrying in ${attempt} seconds` ); - await new Promise(resolve => setTimeout(resolve, attempt * 1000)); + await new Promise((resolve) => setTimeout(resolve, attempt * 1000)); } } } diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts index 4244006f4a3a33..ea4159de557499 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts +++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts @@ -66,7 +66,7 @@ export interface ReqOptions { } const delay = (ms: number) => - new Promise(resolve => { + new Promise((resolve) => { setTimeout(resolve, ms); }); diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts b/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts index 1a292aff303afd..4951bef91c446e 100644 --- a/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts +++ b/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts @@ -33,7 +33,7 @@ export function observeReadable(readable: Readable): Rx.Observable { Rx.fromEvent(readable, 'error').pipe( first(), - mergeMap(err => Rx.throwError(err)) + mergeMap((err) => Rx.throwError(err)) ) ); } diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.ts b/packages/kbn-dev-utils/src/proc_runner/proc.ts index c899293191f2a7..59512cbb133b3e 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc.ts +++ b/packages/kbn-dev-utils/src/proc_runner/proc.ts @@ -118,7 +118,7 @@ export function startProc(name: string, options: ProcOptions, log: ToolingLog) { // observe first error event Rx.fromEvent(childProcess, 'error').pipe( take(1), - mergeMap(err => Rx.throwError(err)) + mergeMap((err) => Rx.throwError(err)) ) ).pipe(share()); @@ -126,7 +126,7 @@ export function startProc(name: string, options: ProcOptions, log: ToolingLog) { observeLines(childProcess.stdout), observeLines(childProcess.stderr) ).pipe( - tap(line => log.write(` ${chalk.gray('proc')} [${chalk.gray(name)}] ${line}`)), + tap((line) => log.write(` ${chalk.gray('proc')} [${chalk.gray(name)}] ${line}`)), share() ); diff --git a/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts index 1759ca2840c5be..c879b4595b451c 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts +++ b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts @@ -50,7 +50,7 @@ export class ProcRunner { constructor(private log: ToolingLog) { this.signalUnsubscribe = exitHook(() => { - this.teardown().catch(error => { + this.teardown().catch((error) => { log.error(`ProcRunner teardown error: ${error.stack}`); }); }); @@ -105,9 +105,9 @@ export class ProcRunner { // wait for process to log matching line await Rx.race( proc.lines$.pipe( - filter(line => wait.test(line)), + filter((line) => wait.test(line)), first(), - catchError(err => { + catchError((err) => { if (err.name !== 'EmptyError') { throw createCliError(`[${name}] exited without matching pattern: ${wait}`); } else { @@ -159,7 +159,7 @@ export class ProcRunner { * @return {Promise} */ async waitForAllToStop() { - await Promise.all(this.procs.map(proc => proc.outcomePromise)); + await Promise.all(this.procs.map((proc) => proc.outcomePromise)); } /** @@ -181,19 +181,19 @@ export class ProcRunner { this.log.warning( '%d processes left running, stop them with procs.stop(name):', this.procs.length, - this.procs.map(proc => proc.name) + this.procs.map((proc) => proc.name) ); } await Promise.all( - this.procs.map(async proc => { + this.procs.map(async (proc) => { await proc.stop(signal === 'exit' ? 'SIGKILL' : signal); }) ); } private getProc(name: string) { - return this.procs.find(proc => { + return this.procs.find((proc) => { return proc.name === name; }); } @@ -209,14 +209,14 @@ export class ProcRunner { // tie into proc outcome$, remove from _procs on compete proc.outcome$.subscribe({ - next: code => { + next: (code) => { const duration = moment.duration(Date.now() - startMs); this.log.info('[%s] exited with %s after %s', name, code, duration.humanize()); }, complete: () => { remove(); }, - error: error => { + error: (error) => { if (this.closing) { this.log.error(error); } diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts index e37bdcc40ca1c5..89127069f4b8d0 100644 --- a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts +++ b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts @@ -22,14 +22,14 @@ import { withProcRunner } from './with_proc_runner'; import { ProcRunner } from './proc_runner'; it('passes proc runner to a function', async () => { - await withProcRunner(new ToolingLog(), async proc => { + await withProcRunner(new ToolingLog(), async (proc) => { expect(proc).toBeInstanceOf(ProcRunner); }); }); it('calls procRunner.teardown() if function returns synchronously', async () => { let teardownSpy; - await withProcRunner(new ToolingLog(), async proc => { + await withProcRunner(new ToolingLog(), async (proc) => { teardownSpy = jest.spyOn(proc, 'teardown'); }); @@ -41,7 +41,7 @@ it('calls procRunner.teardown() if function throw synchronous error, and rejects let teardownSpy; await expect( - withProcRunner(new ToolingLog(), async proc => { + withProcRunner(new ToolingLog(), async (proc) => { teardownSpy = jest.spyOn(proc, 'teardown'); throw error; }) @@ -53,8 +53,8 @@ it('calls procRunner.teardown() if function throw synchronous error, and rejects it('waits for promise to resolve before tearing down proc', async () => { let teardownSpy; - await withProcRunner(new ToolingLog(), async proc => { - await new Promise(resolve => setTimeout(resolve, 500)); + await withProcRunner(new ToolingLog(), async (proc) => { + await new Promise((resolve) => setTimeout(resolve, 500)); teardownSpy = jest.spyOn(proc, 'teardown'); }); @@ -67,8 +67,8 @@ it('waits for promise to reject before tearing down proc and rejecting with the let teardownSpy; await expect( - withProcRunner(new ToolingLog(), async proc => { - await new Promise(resolve => setTimeout(resolve, 500)); + withProcRunner(new ToolingLog(), async (proc) => { + await new Promise((resolve) => setTimeout(resolve, 500)); teardownSpy = jest.spyOn(proc, 'teardown'); throw error; }) diff --git a/packages/kbn-dev-utils/src/run/fail.ts b/packages/kbn-dev-utils/src/run/fail.ts index a2501fc9513bf0..f10ef1d52ef04f 100644 --- a/packages/kbn-dev-utils/src/run/fail.ts +++ b/packages/kbn-dev-utils/src/run/fail.ts @@ -61,7 +61,7 @@ export function combineErrors(errors: Array) { .filter(isFailError) .reduce((acc, error) => Math.max(acc, error.exitCode), 1); - const showHelp = errors.some(error => isFailError(error) && error.showHelp); + const showHelp = errors.some((error) => isFailError(error) && error.showHelp); const message = errors.reduce((acc, error) => { if (isFailError(error)) { diff --git a/packages/kbn-dev-utils/src/run/run.ts b/packages/kbn-dev-utils/src/run/run.ts index 35477e988d8371..894db0d3fdadbe 100644 --- a/packages/kbn-dev-utils/src/run/run.ts +++ b/packages/kbn-dev-utils/src/run/run.ts @@ -62,7 +62,7 @@ export async function run(fn: RunFn, options: Options = {}) { writeTo: process.stdout, }); - process.on('unhandledRejection', error => { + process.on('unhandledRejection', (error) => { log.error('UNHANDLED PROMISE REJECTION'); log.error( error instanceof Error @@ -110,7 +110,7 @@ export async function run(fn: RunFn, options: Options = {}) { } try { - await withProcRunner(log, async procRunner => { + await withProcRunner(log, async (procRunner) => { await fn({ log, flags, diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts index 21f02325cac662..4a0f5ca5f8a5f8 100644 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts @@ -80,29 +80,31 @@ describe('#indent()', () => { }); }); -(['verbose', 'debug', 'info', 'success', 'warning', 'error', 'write'] as const).forEach(method => { - describe(`#${method}()`, () => { - it(`sends a msg of type "${method}" to each writer with indent and arguments`, () => { - const log = new ToolingLog(); - const writeA = jest.fn(); - const writeB = jest.fn(); - - log.setWriters([{ write: writeA }, { write: writeB }]); - - if (method === 'error') { - const error = new Error('error message'); - error.stack = '... stack trace ...'; - log.error(error); - log.error('string message'); - } else { - log[method]('foo', 'bar', 'baz'); - } - - expect(writeA.mock.calls).toMatchSnapshot(); - expect(writeA.mock.calls).toEqual(writeB.mock.calls); +(['verbose', 'debug', 'info', 'success', 'warning', 'error', 'write'] as const).forEach( + (method) => { + describe(`#${method}()`, () => { + it(`sends a msg of type "${method}" to each writer with indent and arguments`, () => { + const log = new ToolingLog(); + const writeA = jest.fn(); + const writeB = jest.fn(); + + log.setWriters([{ write: writeA }, { write: writeB }]); + + if (method === 'error') { + const error = new Error('error message'); + error.stack = '... stack trace ...'; + log.error(error); + log.error('string message'); + } else { + log[method]('foo', 'bar', 'baz'); + } + + expect(writeA.mock.calls).toMatchSnapshot(); + expect(writeA.mock.calls).toEqual(writeB.mock.calls); + }); }); - }); -}); + } +); describe('#getWritten$()', () => { async function testWrittenMsgs(writers: Writer[]) { @@ -110,10 +112,7 @@ describe('#getWritten$()', () => { log.setWriters(writers); const done$ = new Rx.Subject(); - const promise = log - .getWritten$() - .pipe(takeUntil(done$), toArray()) - .toPromise(); + const promise = log.getWritten$().pipe(takeUntil(done$), toArray()).toPromise(); log.debug('foo'); log.info('bar'); diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_collecting_writer.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log_collecting_writer.ts index 46026bdc369d45..7e790770321562 100644 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log_collecting_writer.ts +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log_collecting_writer.ts @@ -26,7 +26,7 @@ export class ToolingLogCollectingWriter extends ToolingLogTextWriter { super({ level: 'verbose', writeTo: { - write: msg => { + write: (msg) => { // trim trailing new line this.messages.push(msg.slice(0, -1)); }, diff --git a/packages/kbn-es/src/artifact.js b/packages/kbn-es/src/artifact.js index 83dcd1cf36d2e5..7d4c7a3fd2c330 100644 --- a/packages/kbn-es/src/artifact.js +++ b/packages/kbn-es/src/artifact.js @@ -60,7 +60,7 @@ async function retry(log, fn) { } log.warning('...failure, retrying in 5 seconds:', error.message); - await new Promise(resolve => setTimeout(resolve, 5000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); log.info('...retrying'); return await doAttempt(attempt + 1); } @@ -120,7 +120,7 @@ async function getArtifactSpecForSnapshot(urlVersion, license, log) { const arch = process.arch === 'arm64' ? 'aarch64' : 'x86_64'; const archive = manifest.archives.find( - archive => + (archive) => archive.version === desiredVersion && archive.platform === platform && archive.license === desiredLicense && diff --git a/packages/kbn-es/src/artifact.test.js b/packages/kbn-es/src/artifact.test.js index 02e4d5318f63f1..bbcf6640060466 100644 --- a/packages/kbn-es/src/artifact.test.js +++ b/packages/kbn-es/src/artifact.test.js @@ -52,14 +52,14 @@ const createArchive = (params = {}) => { }; }; -const mockFetch = mock => +const mockFetch = (mock) => fetch.mockReturnValue(Promise.resolve(new Response(JSON.stringify(mock)))); const previousEnvVars = {}; const ENV_VARS_TO_RESET = ['ES_SNAPSHOT_MANIFEST', 'KBN_ES_SNAPSHOT_USE_UNVERIFIED']; beforeAll(() => { - ENV_VARS_TO_RESET.forEach(key => { + ENV_VARS_TO_RESET.forEach((key) => { if (key in process.env) { previousEnvVars[key] = process.env[key]; delete process.env[key]; @@ -68,7 +68,7 @@ beforeAll(() => { }); afterAll(() => { - Object.keys(previousEnvVars).forEach(key => { + Object.keys(previousEnvVars).forEach((key) => { process.env[key] = previousEnvVars[key]; }); }); diff --git a/packages/kbn-es/src/cli.js b/packages/kbn-es/src/cli.js index ed81e01ccf8abc..61019d27bf3830 100644 --- a/packages/kbn-es/src/cli.js +++ b/packages/kbn-es/src/cli.js @@ -26,7 +26,7 @@ const { log } = require('./utils'); function help() { const availableCommands = Object.keys(commands).map( - name => `${name} - ${commands[name].description}` + (name) => `${name} - ${commands[name].description}` ); console.log(dedent` diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index ceb4a5b6aece14..68bcc37c65600a 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -40,8 +40,8 @@ const readFile = util.promisify(fs.readFile); // listen to data on stream until map returns anything but undefined const first = (stream, map) => - new Promise(resolve => { - const onData = data => { + new Promise((resolve) => { + const onData = (data) => { const result = map(data); if (result !== undefined) { resolve(result); @@ -180,7 +180,7 @@ exports.Cluster = class Cluster { await Promise.race([ // wait for native realm to be setup and es to be started Promise.all([ - first(this._process.stdout, data => { + first(this._process.stdout, (data) => { if (/started/.test(data)) { return true; } @@ -207,7 +207,7 @@ exports.Cluster = class Cluster { this._exec(installPath, options); // log native realm setup errors so they aren't uncaught - this._nativeRealmSetup.catch(error => { + this._nativeRealmSetup.catch((error) => { this._log.error(error); this.stop(); }); @@ -287,7 +287,7 @@ exports.Cluster = class Cluster { }); // parse log output to find http port - const httpPort = first(this._process.stdout, data => { + const httpPort = first(this._process.stdout, (data) => { const match = data.toString('utf8').match(/HttpServer.+publish_address {[0-9.]+:([0-9]+)/); if (match) { @@ -296,7 +296,7 @@ exports.Cluster = class Cluster { }); // once the http port is available setup the native realm - this._nativeRealmSetup = httpPort.then(async port => { + this._nativeRealmSetup = httpPort.then(async (port) => { const caCert = await this._caCertPromise; const nativeRealm = new NativeRealm({ port, @@ -309,19 +309,19 @@ exports.Cluster = class Cluster { }); // parse and forward es stdout to the log - this._process.stdout.on('data', data => { + this._process.stdout.on('data', (data) => { const lines = parseEsLog(data.toString()); - lines.forEach(line => { + lines.forEach((line) => { this._log.info(line.formattedMessage); }); }); // forward es stderr to the log - this._process.stderr.on('data', data => this._log.error(chalk.red(data.toString()))); + this._process.stderr.on('data', (data) => this._log.error(chalk.red(data.toString()))); // observe the exit code of the process and reflect in _outcome promies - const exitCode = new Promise(resolve => this._process.once('exit', resolve)); - this._outcome = exitCode.then(code => { + const exitCode = new Promise((resolve) => this._process.once('exit', resolve)); + this._outcome = exitCode.then((code) => { if (this._stopCalled) { return; } diff --git a/packages/kbn-es/src/errors.js b/packages/kbn-es/src/errors.js index 099b5214bcbdb3..7b39251f1327cd 100644 --- a/packages/kbn-es/src/errors.js +++ b/packages/kbn-es/src/errors.js @@ -17,12 +17,12 @@ * under the License. */ -exports.createCliError = function(message) { +exports.createCliError = function (message) { const error = new Error(message); error.isCliError = true; return error; }; -exports.isCliError = function(error) { +exports.isCliError = function (error) { return error && error.isCliError; }; diff --git a/packages/kbn-es/src/install/source.js b/packages/kbn-es/src/install/source.js index e78e9f1ff4b25b..bfeff736f8cdc8 100644 --- a/packages/kbn-es/src/install/source.js +++ b/packages/kbn-es/src/install/source.js @@ -99,15 +99,11 @@ async function sourceInfo(cwd, license, log = defaultLog) { etag.update(sha); // for changed files, use last modified times in hash calculation - status.files.forEach(file => { + status.files.forEach((file) => { etag.update(fs.statSync(path.join(cwd, file.path)).mtime.toString()); }); - const cwdHash = crypto - .createHash('md5') - .update(cwd) - .digest('hex') - .substr(0, 8); + const cwdHash = crypto.createHash('md5').update(cwd).digest('hex').substr(0, 8); const basename = `${branch}-${task}-${cwdHash}`; const filename = `${basename}.${ext}`; diff --git a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js index d374abe5db0683..b860664443d1ab 100644 --- a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js +++ b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js @@ -71,7 +71,7 @@ const delayServerClose = () => { server.on('request', delayServerClose); server.on('listening', delayServerClose); -server.listen(0, '127.0.0.1', function() { +server.listen(0, '127.0.0.1', function () { const { port, address: hostname } = server.address(); serverUrl = new URL( formatUrl({ diff --git a/packages/kbn-es/src/integration_tests/cluster.test.js b/packages/kbn-es/src/integration_tests/cluster.test.js index dfbc04477bd409..0ae0ac0aac27a4 100644 --- a/packages/kbn-es/src/integration_tests/cluster.test.js +++ b/packages/kbn-es/src/integration_tests/cluster.test.js @@ -37,7 +37,7 @@ jest.mock('../utils/extract_config_files', () => ({ const log = new ToolingLog(); function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } async function ensureNoResolve(promise) { @@ -77,7 +77,7 @@ function mockEsBin({ exitCode, start }) { beforeEach(() => { jest.resetAllMocks(); - extractConfigFiles.mockImplementation(config => config); + extractConfigFiles.mockImplementation((config) => config); }); describe('#installSource()', () => { @@ -85,7 +85,7 @@ describe('#installSource()', () => { let resolveInstallSource; installSource.mockImplementationOnce( () => - new Promise(resolve => { + new Promise((resolve) => { resolveInstallSource = () => { resolve({ installPath: 'foo' }); }; @@ -124,7 +124,7 @@ describe('#installSnapshot()', () => { let resolveInstallSnapshot; installSnapshot.mockImplementationOnce( () => - new Promise(resolve => { + new Promise((resolve) => { resolveInstallSnapshot = () => { resolve({ installPath: 'foo' }); }; @@ -163,7 +163,7 @@ describe('#installArchive(path)', () => { let resolveInstallArchive; installArchive.mockImplementationOnce( () => - new Promise(resolve => { + new Promise((resolve) => { resolveInstallArchive = () => { resolve({ installPath: 'foo' }); }; diff --git a/packages/kbn-es/src/settings.ts b/packages/kbn-es/src/settings.ts index 58eedff207b4da..bf7160b9fee7b1 100644 --- a/packages/kbn-es/src/settings.ts +++ b/packages/kbn-es/src/settings.ts @@ -25,7 +25,7 @@ const SECURE_SETTINGS_LIST = [ ]; function isSecureSetting(settingName: string) { - return SECURE_SETTINGS_LIST.some(secureSettingNameRegex => + return SECURE_SETTINGS_LIST.some((secureSettingNameRegex) => secureSettingNameRegex.test(settingName) ); } diff --git a/packages/kbn-es/src/utils/build_snapshot.js b/packages/kbn-es/src/utils/build_snapshot.js index 3173df700e3035..ce0dc88ac1d7c4 100644 --- a/packages/kbn-es/src/utils/build_snapshot.js +++ b/packages/kbn-es/src/utils/build_snapshot.js @@ -25,7 +25,7 @@ const { createCliError } = require('../errors'); const { findMostRecentlyChanged } = require('../utils'); const { GRADLE_BIN } = require('../paths'); -const onceEvent = (emitter, event) => new Promise(resolve => emitter.once(event, resolve)); +const onceEvent = (emitter, event) => new Promise((resolve) => emitter.once(event, resolve)); /** * Creates archive from source @@ -59,13 +59,13 @@ exports.buildSnapshot = async ({ license, sourcePath, log, platform = os.platfor const stdout = readline.createInterface({ input: build.stdout }); const stderr = readline.createInterface({ input: build.stderr }); - stdout.on('line', line => log.debug(line)); - stderr.on('line', line => log.error(line)); + stdout.on('line', (line) => log.debug(line)); + stderr.on('line', (line) => log.error(line)); const [exitCode] = await Promise.all([ Promise.race([ onceEvent(build, 'exit'), - onceEvent(build, 'error').then(error => { + onceEvent(build, 'error').then((error) => { throw createCliError(`Error spawning gradle: ${error.message}`); }), ]), diff --git a/packages/kbn-es/src/utils/decompress.js b/packages/kbn-es/src/utils/decompress.js index b4299594c50627..1fdb647b1dc0d2 100644 --- a/packages/kbn-es/src/utils/decompress.js +++ b/packages/kbn-es/src/utils/decompress.js @@ -50,15 +50,12 @@ function decompressZip(input, output) { resolve(); }); - zipfile.on('error', err => { + zipfile.on('error', (err) => { reject(err); }); - zipfile.on('entry', entry => { - const zipPath = entry.fileName - .split(/\/|\\/) - .slice(1) - .join(path.sep); + zipfile.on('entry', (entry) => { + const zipPath = entry.fileName.split(/\/|\\/).slice(1).join(path.sep); const fileName = path.resolve(output, zipPath); if (/\/$/.test(entry.fileName)) { @@ -83,7 +80,7 @@ function decompressZip(input, output) { }); } -exports.decompress = async function(input, output) { +exports.decompress = async function (input, output) { const ext = path.extname(input); switch (path.extname(input)) { diff --git a/packages/kbn-es/src/utils/extract_config_files.js b/packages/kbn-es/src/utils/extract_config_files.js index a8a44a149e9b37..d535528cef2393 100644 --- a/packages/kbn-es/src/utils/extract_config_files.js +++ b/packages/kbn-es/src/utils/extract_config_files.js @@ -32,7 +32,7 @@ exports.extractConfigFiles = function extractConfigFiles(config, dest, options = const originalConfig = typeof config === 'string' ? [config] : config; const localConfig = []; - originalConfig.forEach(prop => { + originalConfig.forEach((prop) => { const [key, value] = prop.split('='); if (isFile(value)) { diff --git a/packages/kbn-es/src/utils/find_most_recently_changed.js b/packages/kbn-es/src/utils/find_most_recently_changed.js index 0fcd87978c3579..3ba8865e88d924 100644 --- a/packages/kbn-es/src/utils/find_most_recently_changed.js +++ b/packages/kbn-es/src/utils/find_most_recently_changed.js @@ -32,7 +32,7 @@ exports.findMostRecentlyChanged = function findMostRecentlyChanged(pattern) { throw new TypeError(`Pattern must be absolute, got ${pattern}`); } - const ctime = path => fs.statSync(path).ctime.getTime(); + const ctime = (path) => fs.statSync(path).ctime.getTime(); return glob .sync(pattern) diff --git a/packages/kbn-es/src/utils/find_most_recently_changed.test.js b/packages/kbn-es/src/utils/find_most_recently_changed.test.js index ed90576990c725..ee032686bc6218 100644 --- a/packages/kbn-es/src/utils/find_most_recently_changed.test.js +++ b/packages/kbn-es/src/utils/find_most_recently_changed.test.js @@ -18,7 +18,7 @@ */ jest.mock('fs', () => ({ - statSync: jest.fn().mockImplementation(path => { + statSync: jest.fn().mockImplementation((path) => { if (path.includes('oldest')) { return { ctime: new Date(2018, 2, 1), diff --git a/packages/kbn-es/src/utils/native_realm.js b/packages/kbn-es/src/utils/native_realm.js index 086898abb6b676..573944a8cc6d0a 100644 --- a/packages/kbn-es/src/utils/native_realm.js +++ b/packages/kbn-es/src/utils/native_realm.js @@ -76,28 +76,26 @@ exports.NativeRealm = class NativeRealm { } const reservedUsers = await this.getReservedUsers(); - if (!reservedUsers || reservedUsers.length < 1) { - throw new Error('no reserved users found, unable to set native realm passwords'); - } - await Promise.all( - reservedUsers.map(async user => { + reservedUsers.map(async (user) => { await this.setPassword(user, options[`password.${user}`]); }) ); } async getReservedUsers() { - const users = await this._autoRetry(async () => { - return await this._client.security.getUser(); - }); + return await this._autoRetry(async () => { + const resp = await this._client.security.getUser(); + const usernames = Object.keys(resp.body).filter( + (user) => resp.body[user].metadata._reserved === true + ); - return Object.keys(users.body).reduce((acc, user) => { - if (users.body[user].metadata._reserved === true) { - acc.push(user); + if (!usernames?.length) { + throw new Error('no reserved users found, unable to set native realm passwords'); } - return acc; - }, []); + + return usernames; + }); } async isSecurityEnabled() { @@ -125,10 +123,9 @@ exports.NativeRealm = class NativeRealm { throw error; } - this._log.warning( - 'assuming [elastic] user not available yet, waiting 1.5 seconds and trying again' - ); - await new Promise(resolve => setTimeout(resolve, 1500)); + const sec = 1.5 * attempt; + this._log.warning(`assuming ES isn't initialized completely, trying again in ${sec} seconds`); + await new Promise((resolve) => setTimeout(resolve, sec * 1000)); return await this._autoRetry(fn, attempt + 1); } } diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js index e26660f76a5502..8472aaf0fc0293 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js @@ -31,6 +31,6 @@ // const PATH_IMPORT_RE = /^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/; -exports.getIsPathRequest = function(source) { +exports.getIsPathRequest = function (source) { return PATH_IMPORT_RE.test(source); }; diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js index 93c0f907d628d3..3856281d153202 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js @@ -26,7 +26,7 @@ const DEFAULT_PLUGIN_PATH = '../..'; /* * Resolves the path to Kibana, either from default setting or config */ -exports.getKibanaPath = function(config, projectRoot) { +exports.getKibanaPath = function (config, projectRoot) { const inConfig = config != null && config.kibanaPath; // We only allow `.` in the config as we need it for Kibana itself diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js index 3fb5b5dab77768..445a3cad385fcb 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js @@ -49,10 +49,10 @@ function getPathType(path) { return type; } -exports.isDirectory = function(path) { +exports.isDirectory = function (path) { return getPathType(path) === DIR; }; -exports.isFile = function(path) { +exports.isFile = function (path) { return getPathType(path) === FILE; }; diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js index 319b959883a8ab..84481783b22fc4 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js @@ -21,8 +21,8 @@ const { dirname, resolve } = require('path'); const glob = require('glob-all'); -exports.getPlugins = function(config, kibanaPath, projectRoot) { - const resolveToRoot = path => resolve(projectRoot, path); +exports.getPlugins = function (config, kibanaPath, projectRoot) { + const resolveToRoot = (path) => resolve(projectRoot, path); const pluginDirs = [ ...(config.pluginDirs || []).map(resolveToRoot), @@ -39,11 +39,11 @@ exports.getPlugins = function(config, kibanaPath, projectRoot) { ]; const globPatterns = [ - ...pluginDirs.map(dir => resolve(dir, '*/package.json')), - ...pluginPaths.map(path => resolve(path, 'package.json')), + ...pluginDirs.map((dir) => resolve(dir, '*/package.json')), + ...pluginPaths.map((path) => resolve(path, 'package.json')), ]; - const pluginsFromMap = Object.keys(config.pluginMap || {}).map(name => { + const pluginsFromMap = Object.keys(config.pluginMap || {}).map((name) => { const directory = resolveToRoot(config.pluginMap[name]); return { name, @@ -53,7 +53,7 @@ exports.getPlugins = function(config, kibanaPath, projectRoot) { }); return pluginsFromMap.concat( - glob.sync(globPatterns).map(pkgJsonPath => { + glob.sync(globPatterns).map((pkgJsonPath) => { const path = dirname(pkgJsonPath); const pkg = require(pkgJsonPath); // eslint-disable-line import/no-dynamic-require return { diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js index 5c70d63bf147b8..fed40298d513f9 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js @@ -55,7 +55,7 @@ function getRootPackageDir(dirRoot, dir, rootPackageName) { } } -exports.getProjectRoot = function(file, config) { +exports.getProjectRoot = function (file, config) { const { root, dir } = parse(resolve(file)); const { rootPackageName } = config; diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js index da0b799b338edc..6cb2f3d2901d3a 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js @@ -22,7 +22,7 @@ const { resolve } = require('path'); const { debug } = require('./debug'); const { getPlugins } = require('./get_plugins'); -exports.getWebpackConfig = function(kibanaPath, projectRoot, config) { +exports.getWebpackConfig = function (kibanaPath, projectRoot, config) { const fromKibana = (...path) => resolve(kibanaPath, ...path); const alias = { @@ -39,7 +39,7 @@ exports.getWebpackConfig = function(kibanaPath, projectRoot, config) { test_utils: fromKibana('src/test_utils/public'), }; - getPlugins(config, kibanaPath, projectRoot).forEach(plugin => { + getPlugins(config, kibanaPath, projectRoot).forEach((plugin) => { alias[`plugins/${plugin.name}`] = plugin.publicDirectory; }); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js b/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js index 2af7d1c2f53496..9eb3234fca7b47 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js @@ -32,8 +32,8 @@ function readShimNames(shimDirectory) { } return readdirSync(shimDirectory) - .filter(name => !name.startsWith('.') && !name.startsWith('_')) - .map(name => (name.endsWith('.js') ? name.slice(0, -3) : name)); + .filter((name) => !name.startsWith('.') && !name.startsWith('_')) + .map((name) => (name.endsWith('.js') ? name.slice(0, -3) : name)); } function findRelativeWebpackShims(directory) { @@ -53,7 +53,7 @@ function findRelativeWebpackShims(directory) { return allShims; } -exports.isProbablyWebpackShim = function(source, file) { +exports.isProbablyWebpackShim = function (source, file) { const shims = findRelativeWebpackShims(dirname(file)); - return shims.some(shim => source === shim || source.startsWith(shim + '/')); + return shims.some((shim) => source === shim || source.startsWith(shim + '/')); }; diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js b/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js index a7bb391f9b1c6b..00b07f469bd9cc 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js @@ -25,7 +25,7 @@ * @param {Array<[alias,path]>} aliasEntries * @return {string|undefined} */ -exports.resolveWebpackAlias = function(source, aliasEntries) { +exports.resolveWebpackAlias = function (source, aliasEntries) { for (const [alias, path] of aliasEntries) { if (source === alias) { return path; diff --git a/packages/kbn-eslint-plugin-eslint/lib.js b/packages/kbn-eslint-plugin-eslint/lib.js index 56684746c479f4..a7431be00e0548 100644 --- a/packages/kbn-eslint-plugin-eslint/lib.js +++ b/packages/kbn-eslint-plugin-eslint/lib.js @@ -31,7 +31,7 @@ exports.normalizeWhitespace = function normalizeWhitespace(string) { return string.replace(/\s+/g, ' '); }; -exports.init = function(context, program, initStep) { +exports.init = function (context, program, initStep) { try { return initStep(); } catch (error) { diff --git a/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js b/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js index 577be820ccc7bc..e16ba0d16bb876 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js +++ b/packages/kbn-eslint-plugin-eslint/rules/__tests__/no_restricted_paths.js @@ -196,6 +196,28 @@ ruleTester.run('@kbn/eslint/no-restricted-paths', rule, { ], invalid: [ + { + code: 'export { b } from "../server/b.js"', + filename: path.join(__dirname, './files/no_restricted_paths/client/a.js'), + options: [ + { + basePath: __dirname, + zones: [ + { + target: 'files/no_restricted_paths/client/**/*', + from: 'files/no_restricted_paths/server/**/*', + }, + ], + }, + ], + errors: [ + { + message: 'Unexpected path "../server/b.js" imported in restricted zone.', + line: 1, + column: 19, + }, + ], + }, { code: 'import b from "../server/b.js"', filename: path.join(__dirname, './files/no_restricted_paths/client/a.js'), diff --git a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js index 0567307d18968f..6b5564f1f80041 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js +++ b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js @@ -39,7 +39,7 @@ module.exports = { }, ], }, - create: context => { + create: (context) => { return { Program(program) { const licenses = init(context, program, () => { @@ -70,8 +70,8 @@ module.exports = { sourceCode .getAllComments() - .filter(node => licenses.includes(normalizeWhitespace(node.value))) - .forEach(node => { + .filter((node) => licenses.includes(normalizeWhitespace(node.value))) + .forEach((node) => { context.report({ node, message: 'This license header is not allowed in this file.', diff --git a/packages/kbn-eslint-plugin-eslint/rules/module_migration.js b/packages/kbn-eslint-plugin-eslint/rules/module_migration.js index 8119d338ee5362..6027a939f1a65a 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/module_migration.js +++ b/packages/kbn-eslint-plugin-eslint/rules/module_migration.js @@ -22,7 +22,7 @@ const KIBANA_ROOT = path.resolve(__dirname, '../../..'); function checkModuleNameNode(context, mappings, node) { const mapping = mappings.find( - mapping => mapping.from === node.value || node.value.startsWith(`${mapping.from}/`) + (mapping) => mapping.from === node.value || node.value.startsWith(`${mapping.from}/`) ); if (!mapping) { @@ -105,7 +105,7 @@ module.exports = { }, ], }, - create: context => { + create: (context) => { const mappings = context.options[0]; return { diff --git a/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.js b/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.js index bed10e77597b78..40c53c7f28f6fd 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.js +++ b/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.js @@ -126,6 +126,10 @@ module.exports = { } return { + ExportNamedDeclaration(node) { + if (!node.source) return; + checkForRestrictedImportPath(node.source.value, node.source); + }, ImportDeclaration(node) { checkForRestrictedImportPath(node.source.value, node.source); }, diff --git a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js index f3c9fcef1985ee..915ac3ed7922e9 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js +++ b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js @@ -40,10 +40,10 @@ module.exports = { }, ], }, - create: context => { + create: (context) => { return { Program(program) { - const license = init(context, program, function() { + const license = init(context, program, function () { const options = context.options[0] || {}; const license = options.license; @@ -69,7 +69,7 @@ module.exports = { const sourceCode = context.getSourceCode(); const comment = sourceCode .getAllComments() - .find(node => normalizeWhitespace(node.value) === license.nodeValue); + .find((node) => normalizeWhitespace(node.value) === license.nodeValue); // no licence comment if (!comment) { diff --git a/packages/kbn-i18n/scripts/build.js b/packages/kbn-i18n/scripts/build.js index 0764451c74575c..62e1a35f003994 100644 --- a/packages/kbn-i18n/scripts/build.js +++ b/packages/kbn-i18n/scripts/build.js @@ -31,7 +31,7 @@ const padRight = (width, str) => run( async ({ log, flags }) => { - await withProcRunner(log, async proc => { + await withProcRunner(log, async (proc) => { log.info('Deleting old output'); await del(BUILD_DIR); @@ -43,7 +43,7 @@ run( log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`); await Promise.all([ - ...['web', 'node'].map(subTask => + ...['web', 'node'].map((subTask) => proc.run(padRight(10, `babel:${subTask}`), { cmd: 'babel', args: [ diff --git a/packages/kbn-i18n/src/angular/filter.test.ts b/packages/kbn-i18n/src/angular/filter.test.ts index 78bc2796893573..5336926a64139b 100644 --- a/packages/kbn-i18n/src/angular/filter.test.ts +++ b/packages/kbn-i18n/src/angular/filter.test.ts @@ -28,17 +28,14 @@ import * as i18n from '../core/i18n'; import { i18nFilter as angularI18nFilter } from './filter'; import { I18nProvider, I18nServiceType } from './provider'; -angular - .module('app', []) - .provider('i18n', I18nProvider) - .filter('i18n', angularI18nFilter); +angular.module('app', []).provider('i18n', I18nProvider).filter('i18n', angularI18nFilter); describe('i18nFilter', () => { let filter: I18nServiceType; beforeEach(angular.mock.module('app')); beforeEach( - angular.mock.inject(i18nFilter => { + angular.mock.inject((i18nFilter) => { filter = i18nFilter; }) ); diff --git a/packages/kbn-i18n/src/angular/index.ts b/packages/kbn-i18n/src/angular/index.ts index 8f1e315cab3895..ef30f59d60c25a 100644 --- a/packages/kbn-i18n/src/angular/index.ts +++ b/packages/kbn-i18n/src/angular/index.ts @@ -17,6 +17,11 @@ * under the License. */ -export { I18nProvider, I18nServiceType } from './provider'; +export { I18nProvider } from './provider'; + export { i18nFilter } from './filter'; export { i18nDirective } from './directive'; + +// re-export types: https://github.com/babel/babel-loader/issues/603 +import { I18nServiceType as _I18nServiceType } from './provider'; +export type I18nServiceType = _I18nServiceType; diff --git a/packages/kbn-i18n/src/loader.ts b/packages/kbn-i18n/src/loader.ts index 21f540f588f46f..8231ed36928d83 100644 --- a/packages/kbn-i18n/src/loader.ts +++ b/packages/kbn-i18n/src/loader.ts @@ -127,7 +127,7 @@ export function getRegisteredLocales() { */ export async function getTranslationsByLocale(locale: string): Promise { const files = translationsRegistry[locale] || []; - const notLoadedFiles = files.filter(file => !loadedFiles[file]); + const notLoadedFiles = files.filter((file) => !loadedFiles[file]); if (notLoadedFiles.length) { await loadAndCacheFiles(notLoadedFiles); diff --git a/packages/kbn-i18n/src/react/index.tsx b/packages/kbn-i18n/src/react/index.tsx index b3c6bbe7befbbc..ff30934aad6d1c 100644 --- a/packages/kbn-i18n/src/react/index.tsx +++ b/packages/kbn-i18n/src/react/index.tsx @@ -17,9 +17,11 @@ * under the License. */ +import { InjectedIntl as _InjectedIntl } from 'react-intl'; +export type InjectedIntl = _InjectedIntl; + export { intlShape, - InjectedIntl, FormattedDate, FormattedTime, FormattedRelative, diff --git a/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx b/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx index db879fbae6ff1f..3271ae7c98d2fd 100644 --- a/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx +++ b/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx @@ -37,7 +37,7 @@ function translateFormattedMessageUsingPseudoLocale(message: string) { if (formattedMessageDelimiter !== null) { return message .split(formattedMessageDelimiter[0]) - .map(part => (part.startsWith('ELEMENT-') ? part : translateUsingPseudoLocale(part))) + .map((part) => (part.startsWith('ELEMENT-') ? part : translateUsingPseudoLocale(part))) .join(formattedMessageDelimiter[0]); } diff --git a/packages/kbn-interpreter/.babelrc b/packages/kbn-interpreter/.babelrc index 875cbcde9d0e1d..309b3d5b3233db 100644 --- a/packages/kbn-interpreter/.babelrc +++ b/packages/kbn-interpreter/.babelrc @@ -1,6 +1,7 @@ { "presets": ["@kbn/babel-preset/webpack_preset"], "plugins": [ + "@babel/plugin-transform-modules-commonjs", ["@babel/plugin-transform-runtime", { "regenerator": true }] diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index dee35043211f75..5528511e2f566f 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -18,6 +18,7 @@ "devDependencies": { "@babel/cli": "^7.8.4", "@babel/core": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", "@babel/plugin-transform-runtime": "^7.9.0", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", diff --git a/packages/kbn-interpreter/src/common/lib/arg.js b/packages/kbn-interpreter/src/common/lib/arg.js index 0aa2b52e35acb0..2ab74e50358666 100644 --- a/packages/kbn-interpreter/src/common/lib/arg.js +++ b/packages/kbn-interpreter/src/common/lib/arg.js @@ -30,7 +30,7 @@ export function Arg(config) { this.multi = config.multi == null ? false : config.multi; this.resolve = config.resolve == null ? true : config.resolve; this.options = config.options || []; - this.accepts = type => { + this.accepts = (type) => { if (!this.types.length) return true; return includes(config.types, type); }; diff --git a/packages/kbn-interpreter/src/common/lib/ast.js b/packages/kbn-interpreter/src/common/lib/ast.js index 61cfe94ac955c9..98123f475cd923 100644 --- a/packages/kbn-interpreter/src/common/lib/ast.js +++ b/packages/kbn-interpreter/src/common/lib/ast.js @@ -55,7 +55,7 @@ function getExpressionArgs(block, level = 0) { const argKeys = Object.keys(args); const MAX_LINE_LENGTH = 80; // length before wrapping arguments - return argKeys.map(argKey => + return argKeys.map((argKey) => args[argKey].reduce((acc, arg) => { const argString = getArgumentString(arg, argKey, level); const lineLength = acc.split('\n').pop().length; @@ -86,7 +86,7 @@ function getExpression(chain, level = 0) { const separator = level > 0 ? ' | ' : '\n| '; return chain - .map(chainObj => { + .map((chainObj) => { const type = getType(chainObj); if (type === 'function') { diff --git a/packages/kbn-interpreter/src/common/lib/fn.js b/packages/kbn-interpreter/src/common/lib/fn.js index c6b2fcbe677992..5561c08f9c7d08 100644 --- a/packages/kbn-interpreter/src/common/lib/fn.js +++ b/packages/kbn-interpreter/src/common/lib/fn.js @@ -39,7 +39,7 @@ export function Fn(config) { this.context = config.context || {}; - this.accepts = type => { + this.accepts = (type) => { if (!this.context.types) return true; // If you don't tell us about context, we'll assume you don't care what you get return includes(this.context.types, type); // Otherwise, check it }; diff --git a/packages/kbn-interpreter/src/common/lib/get_by_alias.js b/packages/kbn-interpreter/src/common/lib/get_by_alias.js index d7bb1bbf9e79dc..04c435216b9465 100644 --- a/packages/kbn-interpreter/src/common/lib/get_by_alias.js +++ b/packages/kbn-interpreter/src/common/lib/get_by_alias.js @@ -26,7 +26,7 @@ export function getByAlias(specs, name) { const lowerCaseName = name.toLowerCase(); return Object.values(specs).find(({ name, aliases }) => { if (name.toLowerCase() === lowerCaseName) return true; - return (aliases || []).some(alias => { + return (aliases || []).some((alias) => { return alias.toLowerCase() === lowerCaseName; }); }); diff --git a/packages/kbn-interpreter/src/common/lib/registry.js b/packages/kbn-interpreter/src/common/lib/registry.js index 3b22704b9e9c8a..25b122f400711a 100644 --- a/packages/kbn-interpreter/src/common/lib/registry.js +++ b/packages/kbn-interpreter/src/common/lib/registry.js @@ -48,7 +48,7 @@ export class Registry { } toArray() { - return Object.keys(this._indexed).map(key => this.get(key)); + return Object.keys(this._indexed).map((key) => this.get(key)); } get(name) { diff --git a/packages/kbn-interpreter/src/common/registries.js b/packages/kbn-interpreter/src/common/registries.js index 2c68f5647ca730..9d73433bb2d26b 100644 --- a/packages/kbn-interpreter/src/common/registries.js +++ b/packages/kbn-interpreter/src/common/registries.js @@ -24,7 +24,7 @@ * @param {*} newRegistries - The new set of registries */ export function addRegistries(registries, newRegistries) { - Object.keys(newRegistries).forEach(registryName => { + Object.keys(newRegistries).forEach((registryName) => { if (registries[registryName]) { throw new Error(`There is already a registry named "${registryName}".`); } @@ -41,7 +41,7 @@ export function addRegistries(registries, newRegistries) { * @param {*} specs - The specs to be regsitered (e.g. { types: [], browserFunctions: [] }) */ export function register(registries, specs) { - Object.keys(specs).forEach(registryName => { + Object.keys(specs).forEach((registryName) => { if (!registries[registryName]) { throw new Error(`There is no registry named "${registryName}".`); } @@ -49,7 +49,7 @@ export function register(registries, specs) { if (!registries[registryName].register) { throw new Error(`Registry "${registryName}" must have a register function.`); } - specs[registryName].forEach(f => registries[registryName].register(f)); + specs[registryName].forEach((f) => registries[registryName].register(f)); }); return registries; diff --git a/packages/kbn-interpreter/tasks/build/cli.js b/packages/kbn-interpreter/tasks/build/cli.js index 86df21ee566ace..970e0f88478821 100644 --- a/packages/kbn-interpreter/tasks/build/cli.js +++ b/packages/kbn-interpreter/tasks/build/cli.js @@ -56,7 +56,7 @@ if (flags.help) { process.exit(); } -withProcRunner(log, async proc => { +withProcRunner(log, async (proc) => { log.info('Deleting old output'); await del(BUILD_DIR); @@ -87,7 +87,7 @@ withProcRunner(log, async proc => { ]); log.success('Complete'); -}).catch(error => { +}).catch((error) => { log.error(error); process.exit(1); }); diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts index a2fbe969e34d82..0916f12a7110da 100644 --- a/packages/kbn-optimizer/src/cli.ts +++ b/packages/kbn-optimizer/src/cli.ts @@ -77,8 +77,8 @@ run( const extraPluginScanDirs = ([] as string[]) .concat((flags['scan-dir'] as string | string[]) || []) - .map(p => Path.resolve(p)); - if (!extraPluginScanDirs.every(s => typeof s === 'string')) { + .map((p) => Path.resolve(p)); + if (!extraPluginScanDirs.every((s) => typeof s === 'string')) { throw createFlagError('expected --scan-dir to be a string'); } diff --git a/packages/kbn-optimizer/src/common/array_helpers.test.ts b/packages/kbn-optimizer/src/common/array_helpers.test.ts index 9d45217486ee89..ab5f4b694333e3 100644 --- a/packages/kbn-optimizer/src/common/array_helpers.test.ts +++ b/packages/kbn-optimizer/src/common/array_helpers.test.ts @@ -53,11 +53,7 @@ describe('ascending/descending', () => { ].sort(() => 0.5 - Math.random()); it('sorts items using getters', () => { - expect( - Array.from(values) - .sort(ascending(a, b, c)) - .map(print) - ).toMatchInlineSnapshot(` + expect(Array.from(values).sort(ascending(a, b, c)).map(print)).toMatchInlineSnapshot(` Array [ "1/2/3", "3/2/1", @@ -81,11 +77,7 @@ describe('ascending/descending', () => { ] `); - expect( - Array.from(values) - .sort(descending(a, b, c)) - .map(print) - ).toMatchInlineSnapshot(` + expect(Array.from(values).sort(descending(a, b, c)).map(print)).toMatchInlineSnapshot(` Array [ "9/9/9", "8/foo/8", diff --git a/packages/kbn-optimizer/src/common/bundle.ts b/packages/kbn-optimizer/src/common/bundle.ts index 7581b90d60af23..9e2ad186ba40c7 100644 --- a/packages/kbn-optimizer/src/common/bundle.ts +++ b/packages/kbn-optimizer/src/common/bundle.ts @@ -80,7 +80,7 @@ export class Bundle { return { spec: this.toSpec(), mtimes: entriesToObject( - files.map(p => [p, mtimes.get(p)] as const).sort(ascending(e => e[0])) + files.map((p) => [p, mtimes.get(p)] as const).sort(ascending((e) => e[0])) ), }; } diff --git a/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax.ts b/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax.ts index ba19bdc9c3be7d..aba4451622dcd1 100644 --- a/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax.ts +++ b/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax.ts @@ -130,7 +130,7 @@ export const checks: DisallowedSyntaxCheck[] = [ { name: '[es2018] object spread properties', nodeType: 'ObjectExpression', - test: (n: estree.ObjectExpression) => n.properties.some(p => p.type === 'SpreadElement'), + test: (n: estree.ObjectExpression) => n.properties.some((p) => p.type === 'SpreadElement'), }, // https://github.com/estree/estree/blob/master/es2018.md#template-literals { @@ -142,7 +142,7 @@ export const checks: DisallowedSyntaxCheck[] = [ { name: '[es2018] rest properties', nodeType: 'ObjectPattern', - test: (n: estree.ObjectPattern) => n.properties.some(p => p.type === 'RestElement'), + test: (n: estree.ObjectPattern) => n.properties.some((p) => p.type === 'RestElement'), }, /** diff --git a/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax_plugin.ts b/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax_plugin.ts index 7377462eb267bf..8fb7559f3e22f4 100644 --- a/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax_plugin.ts +++ b/packages/kbn-optimizer/src/common/disallowed_syntax_plugin/disallowed_syntax_plugin.ts @@ -26,8 +26,8 @@ import { parseFilePath } from '../parse_path'; export class DisallowedSyntaxPlugin { apply(compiler: webpack.Compiler) { - compiler.hooks.normalModuleFactory.tap(DisallowedSyntaxPlugin.name, factory => { - factory.hooks.parser.for('javascript/auto').tap(DisallowedSyntaxPlugin.name, parser => { + compiler.hooks.normalModuleFactory.tap(DisallowedSyntaxPlugin.name, (factory) => { + factory.hooks.parser.for('javascript/auto').tap(DisallowedSyntaxPlugin.name, (parser) => { parser.hooks.program.tap(DisallowedSyntaxPlugin.name, (program: acorn.Node) => { const module = parser.state?.current; if (!module || !module.resource) { @@ -43,7 +43,7 @@ export class DisallowedSyntaxPlugin { const failedChecks = new Set(); - AcornWalk.full(program, node => { + AcornWalk.full(program, (node) => { const checks = checksByNodeType.get(node.type as any); if (!checks) { return; @@ -63,7 +63,7 @@ export class DisallowedSyntaxPlugin { // throw an error to trigger a parse failure, causing this module to be reported as invalid throw new Error( `disallowed syntax found in file ${resource}:\n - ${Array.from(failedChecks) - .map(c => c.name) + .map((c) => c.name) .join('\n - ')}` ); }); diff --git a/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts b/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts index f6f6841532799a..7458fa13eccb33 100644 --- a/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts +++ b/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts @@ -233,6 +233,6 @@ it('stops an infinite stream when unsubscribed', async () => { // ensure summarizer still only called 10 times after a timeout expect(summarize).toHaveBeenCalledTimes(10); - await new Promise(resolve => setTimeout(resolve, 1000)); + await new Promise((resolve) => setTimeout(resolve, 1000)); expect(summarize).toHaveBeenCalledTimes(10); }); diff --git a/packages/kbn-optimizer/src/common/event_stream_helpers.ts b/packages/kbn-optimizer/src/common/event_stream_helpers.ts index d07af32f88897b..d93cba5653abd9 100644 --- a/packages/kbn-optimizer/src/common/event_stream_helpers.ts +++ b/packages/kbn-optimizer/src/common/event_stream_helpers.ts @@ -40,7 +40,7 @@ export const summarizeEventStream = ( initialState: State, summarize: Summarizer ) => { - return new Rx.Observable>(subscriber => { + return new Rx.Observable>((subscriber) => { const eventBuffer: Event[] = []; let processingEventBuffer = false; @@ -93,7 +93,7 @@ export const summarizeEventStream = ( subscriber.add( event$.subscribe( injectEvent, - error => { + (error) => { subscriber.error(error); }, () => { diff --git a/packages/kbn-optimizer/src/common/parse_path.test.ts b/packages/kbn-optimizer/src/common/parse_path.test.ts index 61be44348cfae5..48749a08fb285c 100644 --- a/packages/kbn-optimizer/src/common/parse_path.test.ts +++ b/packages/kbn-optimizer/src/common/parse_path.test.ts @@ -32,13 +32,13 @@ const FILES = [ ]; describe('parseFilePath()', () => { - it.each([...FILES, ...AMBIGUOUS])('parses %s', path => { + it.each([...FILES, ...AMBIGUOUS])('parses %s', (path) => { expect(parseFilePath(path)).toMatchSnapshot(); }); }); describe('parseDirPath()', () => { - it.each([...DIRS, ...AMBIGUOUS])('parses %s', path => { + it.each([...DIRS, ...AMBIGUOUS])('parses %s', (path) => { expect(parseDirPath(path)).toMatchSnapshot(); }); }); diff --git a/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts b/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts index 72be71e6bf7ec7..dda66c999b8f11 100644 --- a/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts +++ b/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts @@ -29,9 +29,9 @@ describe('pipeClosure()', () => { let counter = 0; const foo$ = Rx.of(1, 2, 3).pipe( - pipeClosure(source$ => { + pipeClosure((source$) => { const multiplier = ++counter; - return source$.pipe(map(i => i * multiplier)); + return source$.pipe(map((i) => i * multiplier)); }), toArray() ); @@ -71,7 +71,7 @@ describe('maybe()', () => { describe('maybeMap()', () => { it('calls map fn and filters out undefined values returned', async () => { const foo$ = Rx.of(1, 2, 3, 4, 5).pipe( - maybeMap(i => (i % 2 ? i : undefined)), + maybeMap((i) => (i % 2 ? i : undefined)), toArray() ); @@ -94,7 +94,7 @@ describe('debounceTimeBuffer()', () => { foo$ .pipe( debounceTimeBuffer(100), - map(items => items.reduce((sum, n) => sum + n)) + map((items) => items.reduce((sum, n) => sum + n)) ) .subscribe(dest); @@ -128,7 +128,7 @@ describe('debounceTimeBuffer()', () => { foo$ .pipe( debounceTimeBuffer(100), - map(items => items.reduce((sum, n) => sum + n)) + map((items) => items.reduce((sum, n) => sum + n)) ) .subscribe(dest); diff --git a/packages/kbn-optimizer/src/common/rxjs_helpers.ts b/packages/kbn-optimizer/src/common/rxjs_helpers.ts index f37bebb49efe9a..c6385c22518aac 100644 --- a/packages/kbn-optimizer/src/common/rxjs_helpers.ts +++ b/packages/kbn-optimizer/src/common/rxjs_helpers.ts @@ -39,7 +39,7 @@ export const pipeClosure = (fn: Operator): Operator => { * supporting TypeScript */ export const maybe = (): Operator => { - return mergeMap(item => (item === undefined ? Rx.EMPTY : [item])); + return mergeMap((item) => (item === undefined ? Rx.EMPTY : [item])); }; /** @@ -64,7 +64,7 @@ export const debounceTimeBuffer = (ms: number) => pipeClosure((source$: Rx.Observable) => { const buffer: T[] = []; return source$.pipe( - tap(item => buffer.push(item)), + tap((item) => buffer.push(item)), debounceTime(ms), map(() => { const items = Array.from(buffer); diff --git a/packages/kbn-optimizer/src/common/worker_config.ts b/packages/kbn-optimizer/src/common/worker_config.ts index c999260872d0f8..3fb1880a73716f 100644 --- a/packages/kbn-optimizer/src/common/worker_config.ts +++ b/packages/kbn-optimizer/src/common/worker_config.ts @@ -31,6 +31,8 @@ export interface WorkerConfig { readonly optimizerCacheKey: unknown; } +export type CacheableWorkerConfig = Omit; + export function parseWorkerConfig(json: string): WorkerConfig { try { if (typeof json !== 'string') { diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index fe0f75c05c6466..8bf5eb72523ffc 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -1,7 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`builds expected bundles, saves bundle counts to metadata: 1 async bundle 1`] = `"(window[\\"foo_bundle_jsonpfunction\\"]=window[\\"foo_bundle_jsonpfunction\\"]||[]).push([[1],{3:function(module,exports,__webpack_require__){\\"use strict\\";Object.defineProperty(exports,\\"__esModule\\",{value:true});exports.foo=foo;function foo(){}}}]);"`; - exports[`builds expected bundles, saves bundle counts to metadata: OptimizerConfig 1`] = ` OptimizerConfig { "bundles": Array [ @@ -31,7 +29,7 @@ OptimizerConfig { }, ], "cache": true, - "dist": true, + "dist": false, "inspectWorkers": false, "maxWorkerCount": 1, "plugins": Array [ @@ -57,6 +55,8 @@ OptimizerConfig { } `; -exports[`builds expected bundles, saves bundle counts to metadata: bar bundle 1`] = `"var __kbnBundles__=typeof __kbnBundles__===\\"object\\"?__kbnBundles__:{};__kbnBundles__[\\"plugin/bar\\"]=function(modules){function webpackJsonpCallback(data){var chunkIds=data[0];var moreModules=data[1];var moduleId,chunkId,i=0,resolves=[];for(;i { await del(TMP_DIR); await cpy('**/*', MOCK_REPO_DIR, { @@ -52,23 +65,11 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { repoRoot: MOCK_REPO_DIR, pluginScanDirs: [Path.resolve(MOCK_REPO_DIR, 'plugins')], maxWorkerCount: 1, - dist: true, + dist: false, }); expect(config).toMatchSnapshot('OptimizerConfig'); - const log = new ToolingLog({ - level: 'error', - writeTo: { - write(chunk) { - if (chunk.endsWith('\n')) { - chunk = chunk.slice(0, -1); - } - // eslint-disable-next-line no-console - console.error(chunk); - }, - }, - }); const msgs = await runOptimizer(config) .pipe(logOptimizerState(log, config), toArray()) .toPromise(); @@ -84,39 +85,39 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { } }; - const initializingStates = msgs.filter(msg => msg.state.phase === 'initializing'); + const initializingStates = msgs.filter((msg) => msg.state.phase === 'initializing'); assert('produce at least one initializing event', initializingStates.length >= 1); const bundleCacheStates = msgs.filter( - msg => + (msg) => (msg.event?.type === 'bundle cached' || msg.event?.type === 'bundle not cached') && msg.state.phase === 'initializing' ); assert('produce two bundle cache events while initializing', bundleCacheStates.length === 2); - const initializedStates = msgs.filter(msg => msg.state.phase === 'initialized'); + const initializedStates = msgs.filter((msg) => msg.state.phase === 'initialized'); assert('produce at least one initialized event', initializedStates.length >= 1); - const workerStarted = msgs.filter(msg => msg.event?.type === 'worker started'); + const workerStarted = msgs.filter((msg) => msg.event?.type === 'worker started'); assert('produce one worker started event', workerStarted.length === 1); - const runningStates = msgs.filter(msg => msg.state.phase === 'running'); + const runningStates = msgs.filter((msg) => msg.state.phase === 'running'); assert( 'produce two or three "running" states', runningStates.length === 2 || runningStates.length === 3 ); - const bundleNotCachedEvents = msgs.filter(msg => msg.event?.type === 'bundle not cached'); + const bundleNotCachedEvents = msgs.filter((msg) => msg.event?.type === 'bundle not cached'); assert('produce two "bundle not cached" events', bundleNotCachedEvents.length === 2); - const successStates = msgs.filter(msg => msg.state.phase === 'success'); + const successStates = msgs.filter((msg) => msg.state.phase === 'success'); assert( 'produce one or two "compiler success" states', successStates.length === 1 || successStates.length === 2 ); const otherStates = msgs.filter( - msg => + (msg) => msg.state.phase !== 'initializing' && msg.state.phase !== 'success' && msg.state.phase !== 'running' && @@ -125,14 +126,7 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { ); assert('produce zero unexpected states', otherStates.length === 0, otherStates); - expectFileMatchesSnapshotWithCompression('plugins/foo/target/public/foo.plugin.js', 'foo bundle'); - expectFileMatchesSnapshotWithCompression( - 'plugins/foo/target/public/1.plugin.js', - '1 async bundle' - ); - expectFileMatchesSnapshotWithCompression('plugins/bar/target/public/bar.plugin.js', 'bar bundle'); - - const foo = config.bundles.find(b => b.id === 'foo')!; + const foo = config.bundles.find((b) => b.id === 'foo')!; expect(foo).toBeTruthy(); foo.cache.refresh(); expect(foo.cache.getModuleCount()).toBe(4); @@ -145,7 +139,7 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { ] `); - const bar = config.bundles.find(b => b.id === 'bar')!; + const bar = config.bundles.find((b) => b.id === 'bar')!; expect(bar).toBeTruthy(); bar.cache.refresh(); expect(bar.cache.getModuleCount()).toBe( @@ -174,12 +168,12 @@ it('uses cache on second run and exist cleanly', async () => { repoRoot: MOCK_REPO_DIR, pluginScanDirs: [Path.resolve(MOCK_REPO_DIR, 'plugins')], maxWorkerCount: 1, - dist: true, + dist: false, }); const msgs = await runOptimizer(config) .pipe( - tap(state => { + tap((state) => { if (state.event?.type === 'worker stdio') { // eslint-disable-next-line no-console console.log('worker', state.event.stream, state.event.chunk.toString('utf8')); @@ -189,7 +183,7 @@ it('uses cache on second run and exist cleanly', async () => { ) .toPromise(); - expect(msgs.map(m => m.state.phase)).toMatchInlineSnapshot(` + expect(msgs.map((m) => m.state.phase)).toMatchInlineSnapshot(` Array [ "initializing", "initializing", @@ -200,6 +194,24 @@ it('uses cache on second run and exist cleanly', async () => { `); }); +it('prepares assets for distribution', async () => { + const config = OptimizerConfig.create({ + repoRoot: MOCK_REPO_DIR, + pluginScanDirs: [Path.resolve(MOCK_REPO_DIR, 'plugins')], + maxWorkerCount: 1, + dist: true, + }); + + await runOptimizer(config).pipe(logOptimizerState(log, config), toArray()).toPromise(); + + expectFileMatchesSnapshotWithCompression('plugins/foo/target/public/foo.plugin.js', 'foo bundle'); + expectFileMatchesSnapshotWithCompression( + 'plugins/foo/target/public/1.plugin.js', + '1 async bundle' + ); + expectFileMatchesSnapshotWithCompression('plugins/bar/target/public/bar.plugin.js', 'bar bundle'); +}); + /** * Verifies that the file matches the expected output and has matching compressed variants. */ diff --git a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts index 1bfd8d3fd073a2..14ff320173d601 100644 --- a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts @@ -35,7 +35,7 @@ const MOCK_REPO_DIR = Path.resolve(TMP_DIR, 'mock_repo'); expect.addSnapshotSerializer({ print: () => '', - test: v => v instanceof Bundle, + test: (v) => v instanceof Bundle, }); expect.addSnapshotSerializer(createAbsolutePathSerializer(MOCK_REPO_DIR)); diff --git a/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts b/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts index c02a857883a988..91d0f308e0ef6f 100644 --- a/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts @@ -96,7 +96,7 @@ it('notifies of changes and completes once all bundles have changed', async () = // first we change foo and bar, and after 1 second get that change comes though if (i === 1) { expect(event.bundles).toHaveLength(2); - const [bar, foo] = event.bundles.sort(ascending(b => b.id)); + const [bar, foo] = event.bundles.sort(ascending((b) => b.id)); expect(bar).toHaveProperty('id', 'bar'); expect(foo).toHaveProperty('id', 'foo'); } @@ -110,7 +110,7 @@ it('notifies of changes and completes once all bundles have changed', async () = // finally we change box and car together if (i === 5) { expect(event.bundles).toHaveLength(2); - const [bar, foo] = event.bundles.sort(ascending(b => b.id)); + const [bar, foo] = event.bundles.sort(ascending((b) => b.id)); expect(bar).toHaveProperty('id', 'box'); expect(foo).toHaveProperty('id', 'car'); } diff --git a/packages/kbn-optimizer/src/log_optimizer_state.ts b/packages/kbn-optimizer/src/log_optimizer_state.ts index 5217581d1b4134..cbec159bd27a02 100644 --- a/packages/kbn-optimizer/src/log_optimizer_state.ts +++ b/packages/kbn-optimizer/src/log_optimizer_state.ts @@ -33,7 +33,7 @@ export function logOptimizerState(log: ToolingLog, config: OptimizerConfig) { let loggedInit = false; return update$.pipe( - tap(update => { + tap((update) => { const { event, state } = update; if (event?.type === 'worker stdio') { diff --git a/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.test.ts b/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.test.ts index dd4d5c294dfc85..4671276797049c 100644 --- a/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.test.ts +++ b/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.test.ts @@ -35,7 +35,7 @@ const summarizeBundles = (w: Assignments) => const readConfigs = (workers: Assignments[]) => workers.map( - (w, i) => `worker ${i} (${summarizeBundles(w)}) => ${w.bundles.map(b => b.id).join(',')}` + (w, i) => `worker ${i} (${summarizeBundles(w)}) => ${w.bundles.map((b) => b.id).join(',')}` ); const assertReturnVal = (workers: Assignments[]) => { diff --git a/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.ts b/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.ts index 001783b167c7a5..e1bcb22230bf9f 100644 --- a/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.ts +++ b/packages/kbn-optimizer/src/optimizer/assign_bundles_to_workers.ts @@ -70,16 +70,16 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number * counts and sort them by [moduleCount, id] */ const bundlesWithCountsDesc = bundles - .filter(b => b.cache.getModuleCount() !== undefined) + .filter((b) => b.cache.getModuleCount() !== undefined) .sort( descending( - b => b.cache.getModuleCount(), - b => b.id + (b) => b.cache.getModuleCount(), + (b) => b.id ) ); const bundlesWithoutModuleCounts = bundles - .filter(b => b.cache.getModuleCount() === undefined) - .sort(descending(b => b.id)); + .filter((b) => b.cache.getModuleCount() === undefined) + .sort(descending((b) => b.id)); /** * assign largest bundles to the smallest worker until it is @@ -87,7 +87,7 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number * with module counts are assigned */ while (bundlesWithCountsDesc.length) { - const [smallestWorker, nextSmallestWorker] = workers.sort(ascending(w => w.moduleCount)); + const [smallestWorker, nextSmallestWorker] = workers.sort(ascending((w) => w.moduleCount)); while (!nextSmallestWorker || smallestWorker.moduleCount <= nextSmallestWorker.moduleCount) { const bundle = bundlesWithCountsDesc.shift(); @@ -104,7 +104,7 @@ export function assignBundlesToWorkers(bundles: Bundle[], maxWorkerCount: number * assign bundles without module counts to workers round-robin * starting with the smallest workers */ - workers.sort(ascending(w => w.moduleCount)); + workers.sort(ascending((w) => w.moduleCount)); while (bundlesWithoutModuleCounts.length) { for (const worker of workers) { const bundle = bundlesWithoutModuleCounts.shift(); diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts index 7750f9145667e9..d5b0b8491f7278 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts @@ -35,7 +35,7 @@ jest.mock('./get_changes.ts', () => ({ })); jest.mock('./get_mtimes.ts', () => ({ - getMtimes: async (paths: string[]) => new Map(paths.map(path => [path, 12345])), + getMtimes: async (paths: string[]) => new Map(paths.map((path) => [path, 12345])), })); jest.mock('execa'); @@ -103,9 +103,7 @@ describe('getOptimizerCacheKey()', () => { "cache": true, "dist": false, "optimizerCacheKey": "♻", - "profileWebpack": false, "repoRoot": , - "watch": false, }, } `); diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.ts index af6a8a648d29cb..e024af125312d2 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.ts @@ -28,7 +28,7 @@ import stripAnsi from 'strip-ansi'; import jestDiff from 'jest-diff'; import jsonStable from 'json-stable-stringify'; -import { ascending, WorkerConfig } from '../common'; +import { ascending, CacheableWorkerConfig } from '../common'; import { getMtimes } from './get_mtimes'; import { getChanges } from './get_changes'; @@ -37,6 +37,16 @@ import { OptimizerConfig } from './optimizer_config'; const OPTIMIZER_DIR = Path.dirname(require.resolve('../../package.json')); const RELATIVE_DIR = Path.relative(REPO_ROOT, OPTIMIZER_DIR); +function omit(obj: T, keys: K[]): Omit { + const result: any = {}; + for (const [key, value] of Object.entries(obj) as any) { + if (!keys.includes(key)) { + result[key] = value; + } + } + return result as Omit; +} + export function diffCacheKey(expected?: unknown, actual?: unknown) { if (jsonStable(expected) === jsonStable(actual)) { return; @@ -119,7 +129,7 @@ export function reformatJestDiff(diff: string | null) { export interface OptimizerCacheKey { readonly lastCommit: string | undefined; readonly bootstrap: string | undefined; - readonly workerConfig: WorkerConfig; + readonly workerConfig: CacheableWorkerConfig; readonly deletedPaths: string[]; readonly modifiedTimes: Record; } @@ -164,15 +174,15 @@ export async function getOptimizerCacheKey(config: OptimizerConfig) { } const cacheKeys: OptimizerCacheKey = { - workerConfig: config.getWorkerConfig('♻'), lastCommit, bootstrap, deletedPaths, modifiedTimes: {} as Record, + workerConfig: omit(config.getWorkerConfig('♻'), ['watch', 'profileWebpack']), }; const mtimes = await getMtimes(modifiedPaths); - for (const [path, mtime] of Array.from(mtimes.entries()).sort(ascending(e => e[0]))) { + for (const [path, mtime] of Array.from(mtimes.entries()).sort(ascending((e) => e[0]))) { if (typeof mtime === 'number') { cacheKeys.modifiedTimes[path] = mtime; } diff --git a/packages/kbn-optimizer/src/optimizer/get_mtimes.ts b/packages/kbn-optimizer/src/optimizer/get_mtimes.ts index 9ac156cb5b8de2..07777c323637a1 100644 --- a/packages/kbn-optimizer/src/optimizer/get_mtimes.ts +++ b/packages/kbn-optimizer/src/optimizer/get_mtimes.ts @@ -33,15 +33,15 @@ export async function getMtimes(paths: Iterable) { // map paths to [path, mtimeMs] entries with concurrency of // 100 at a time, ignoring missing paths mergeMap( - path => + (path) => stat$(path).pipe( - map(stat => [path, stat.mtimeMs] as const), + map((stat) => [path, stat.mtimeMs] as const), catchError((error: any) => (error?.code === 'ENOENT' ? Rx.EMPTY : Rx.throwError(error))) ), 100 ), toArray(), - map(entries => new Map(entries)) + map((entries) => new Map(entries)) ) .toPromise(); } diff --git a/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.test.ts b/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.test.ts index 36dc0ca64c6ca8..2174c488ad6cc4 100644 --- a/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.test.ts +++ b/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.test.ts @@ -44,7 +44,7 @@ it('returns a bundle for core and each plugin', () => { }, ], '/repo' - ).map(b => b.toSpec()) + ).map((b) => b.toSpec()) ).toMatchInlineSnapshot(` Array [ Object { diff --git a/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.ts b/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.ts index 4741cc3c30af70..b75a8a6edc2647 100644 --- a/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.ts +++ b/packages/kbn-optimizer/src/optimizer/get_plugin_bundles.ts @@ -25,9 +25,9 @@ import { KibanaPlatformPlugin } from './kibana_platform_plugins'; export function getPluginBundles(plugins: KibanaPlatformPlugin[], repoRoot: string) { return plugins - .filter(p => p.isUiPlugin) + .filter((p) => p.isUiPlugin) .map( - p => + (p) => new Bundle({ type: 'plugin', id: p.id, diff --git a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts index b4b02649259a29..8b39b5fe8d3b6a 100644 --- a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts +++ b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.ts @@ -32,7 +32,7 @@ export function handleOptimizerCompletion(config: OptimizerConfig) { return update$.pipe( tap({ - next: update => { + next: (update) => { prevState = update.state; }, complete: () => { diff --git a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts index 2165878e92ff4d..992feab6cd364c 100644 --- a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts +++ b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts @@ -36,15 +36,15 @@ export function findKibanaPlatformPlugins(scanDirs: string[], paths: string[]) { .sync( Array.from( new Set([ - ...scanDirs.map(dir => `${dir}/*/kibana.json`), - ...paths.map(path => `${path}/kibana.json`), + ...scanDirs.map((dir) => `${dir}/*/kibana.json`), + ...paths.map((path) => `${path}/kibana.json`), ]) ), { absolute: true, } ) - .map(path => + .map((path) => // absolute paths returned from globby are using normalize or something so the path separators are `/` even on windows, Path.resolve solves this readKibanaPlatformPlugin(Path.resolve(path)) ); diff --git a/packages/kbn-optimizer/src/optimizer/observe_worker.ts b/packages/kbn-optimizer/src/optimizer/observe_worker.ts index bfc853e5a6b750..f5c944cefb76fe 100644 --- a/packages/kbn-optimizer/src/optimizer/observe_worker.ts +++ b/packages/kbn-optimizer/src/optimizer/observe_worker.ts @@ -47,7 +47,7 @@ interface ProcResource extends Rx.Unsubscribable { const isNumeric = (input: any) => String(input).match(/^[0-9]+$/); let inspectPortCounter = 9230; -const inspectFlagIndex = process.execArgv.findIndex(flag => flag.startsWith('--inspect')); +const inspectFlagIndex = process.execArgv.findIndex((flag) => flag.startsWith('--inspect')); let inspectFlag: string | undefined; if (inspectFlagIndex !== -1) { const argv = process.execArgv[inspectFlagIndex]; @@ -74,7 +74,7 @@ function usingWorkerProc( ) { return Rx.using( (): ProcResource => { - const args = [JSON.stringify(workerConfig), JSON.stringify(bundles.map(b => b.toSpec()))]; + const args = [JSON.stringify(workerConfig), JSON.stringify(bundles.map((b) => b.toSpec()))]; const proc = fork(require.resolve('../worker/run_worker'), args, { stdio: ['ignore', 'pipe', 'pipe', 'ipc'], @@ -94,7 +94,7 @@ function usingWorkerProc( }; }, - resource => { + (resource) => { const { proc } = resource as ProcResource; return fn(proc); } @@ -107,7 +107,7 @@ function observeStdio$(stream: Readable, name: WorkerStdio['stream']) { Rx.race( Rx.fromEvent(stream, 'end'), Rx.fromEvent(stream, 'error').pipe( - map(error => { + map((error) => { throw error; }) ) @@ -134,7 +134,7 @@ export function observeWorker( workerConfig: WorkerConfig, bundles: Bundle[] ): Rx.Observable { - return usingWorkerProc(config, workerConfig, bundles, proc => { + return usingWorkerProc(config, workerConfig, bundles, (proc) => { let lastMsg: WorkerMsg; return Rx.merge( @@ -161,7 +161,7 @@ export function observeWorker( Rx.race( // throw into stream on error events Rx.fromEvent(proc, 'error').pipe( - map(error => { + map((error) => { throw new Error(`worker failed to spawn: ${error.message}`); }) ), diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index d6336cf8674705..4ed241f3b9b2ec 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -106,7 +106,7 @@ export class OptimizerConfig { ...(examples ? [Path.resolve('examples'), Path.resolve('x-pack/examples')] : []), Path.resolve(repoRoot, '../kibana-extra'), ]; - if (!pluginScanDirs.every(p => Path.isAbsolute(p))) { + if (!pluginScanDirs.every((p) => Path.isAbsolute(p))) { throw new TypeError('pluginScanDirs must all be absolute paths'); } @@ -118,7 +118,7 @@ export class OptimizerConfig { } const pluginPaths = options.pluginPaths || []; - if (!pluginPaths.every(s => Path.isAbsolute(s))) { + if (!pluginPaths.every((s) => Path.isAbsolute(s))) { throw new TypeError('pluginPaths must all be absolute paths'); } diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_state.ts b/packages/kbn-optimizer/src/optimizer/optimizer_state.ts index ac2a9b8ce1f8b7..1572f459e6ee5f 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_state.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_state.ts @@ -80,7 +80,7 @@ function createOptimizerState( * calculate the total state, given a set of compiler messages */ function getStatePhase(states: CompilerMsg[]) { - const types = states.map(s => s.type); + const types = states.map((s) => s.type); if (types.includes('running')) { return 'running'; @@ -90,7 +90,7 @@ function getStatePhase(states: CompilerMsg[]) { return 'issue'; } - if (types.every(s => s === 'compiler success')) { + if (types.every((s) => s === 'compiler success')) { return 'success'; } @@ -173,7 +173,7 @@ export function createOptimizerStateSummarizer( event.type === 'running' ) { const compilerStates: CompilerMsg[] = [ - ...state.compilerStates.filter(c => c.bundleId !== event.bundleId), + ...state.compilerStates.filter((c) => c.bundleId !== event.bundleId), event, ]; return createOptimizerState(state, { diff --git a/packages/kbn-optimizer/src/optimizer/run_workers.ts b/packages/kbn-optimizer/src/optimizer/run_workers.ts index e91b0d25fd72b9..1f277f011004d2 100644 --- a/packages/kbn-optimizer/src/optimizer/run_workers.ts +++ b/packages/kbn-optimizer/src/optimizer/run_workers.ts @@ -50,15 +50,15 @@ export function runWorkers( return Rx.concat( // first batch of bundles are based on how up-to-date the cache is bundleCache$.pipe( - maybeMap(event => (event.type === 'bundle not cached' ? event.bundle : undefined)), + maybeMap((event) => (event.type === 'bundle not cached' ? event.bundle : undefined)), toArray() ), // subsequent batches are defined by changeEvent$ - changeEvent$.pipe(maybeMap(c => (c.type === 'changes' ? c.bundles : undefined))) + changeEvent$.pipe(maybeMap((c) => (c.type === 'changes' ? c.bundles : undefined))) ).pipe( - mergeMap(bundles => + mergeMap((bundles) => Rx.from(assignBundlesToWorkers(bundles, config.maxWorkerCount)).pipe( - mergeMap(assignment => + mergeMap((assignment) => observeWorker(config, config.getWorkerConfig(optimizerCacheKey), assignment.bundles) ) ) diff --git a/packages/kbn-optimizer/src/optimizer/watch_bundles_for_changes.ts b/packages/kbn-optimizer/src/optimizer/watch_bundles_for_changes.ts index 9149c483786fc5..fdac4e0204fbeb 100644 --- a/packages/kbn-optimizer/src/optimizer/watch_bundles_for_changes.ts +++ b/packages/kbn-optimizer/src/optimizer/watch_bundles_for_changes.ts @@ -38,7 +38,7 @@ function recursiveGetNextChange$( return !bundles.length ? Rx.EMPTY : watcher.getNextChange$(bundles, startTime).pipe( - mergeMap(event => { + mergeMap((event) => { if (event.type === 'changes detected') { return Rx.of(event); } @@ -48,7 +48,7 @@ function recursiveGetNextChange$( recursiveGetNextChange$( watcher, - bundles.filter(b => !event.bundles.includes(b)), + bundles.filter((b) => !event.bundles.includes(b)), Date.now() ) ); @@ -74,11 +74,11 @@ export function watchBundlesForChanges$( initialStartTime: number ) { return bundleCacheEvent$.pipe( - maybeMap(event => (event.type === 'bundle cached' ? event.bundle : undefined)), + maybeMap((event) => (event.type === 'bundle cached' ? event.bundle : undefined)), toArray(), - mergeMap(bundles => + mergeMap((bundles) => bundles.length - ? Watcher.using(watcher => recursiveGetNextChange$(watcher, bundles, initialStartTime)) + ? Watcher.using((watcher) => recursiveGetNextChange$(watcher, bundles, initialStartTime)) : Rx.EMPTY ) ); diff --git a/packages/kbn-optimizer/src/optimizer/watcher.ts b/packages/kbn-optimizer/src/optimizer/watcher.ts index 343f391921383d..54c548755af5c3 100644 --- a/packages/kbn-optimizer/src/optimizer/watcher.ts +++ b/packages/kbn-optimizer/src/optimizer/watcher.ts @@ -43,7 +43,7 @@ export class Watcher { static using(fn: (watcher: Watcher) => Rx.Observable) { return Rx.using( () => new Watcher(), - resource => fn(resource as Watcher) + (resource) => fn(resource as Watcher) ); } @@ -69,14 +69,14 @@ export class Watcher { // debounce and bufffer change events for 1 second to create // final change notification this.change$.pipe( - map(event => event[0]), + map((event) => event[0]), debounceTimeBuffer(1000), map( (changes): Changes => ({ type: 'changes', - bundles: bundles.filter(bundle => { + bundles: bundles.filter((bundle) => { const referencedFiles = bundle.cache.getReferencedFiles(); - return changes.some(change => referencedFiles?.includes(change)); + return changes.some((change) => referencedFiles?.includes(change)); }), }) ), diff --git a/packages/kbn-optimizer/src/report_optimizer_stats.ts b/packages/kbn-optimizer/src/report_optimizer_stats.ts index 06161fb2567b94..5f3153bff51754 100644 --- a/packages/kbn-optimizer/src/report_optimizer_stats.ts +++ b/packages/kbn-optimizer/src/report_optimizer_stats.ts @@ -29,14 +29,14 @@ export function reportOptimizerStats(reporter: CiStatsReporter, config: Optimize let lastState: OptimizerState | undefined; return update$.pipe( materialize(), - mergeMap(async n => { + mergeMap(async (n) => { if (n.kind === 'N' && n.value?.state) { lastState = n.value?.state; } if (n.kind === 'C' && lastState) { await reporter.metrics( - config.bundles.map(bundle => { + config.bundles.map((bundle) => { // make the cache read from the cache file since it was likely updated by the worker bundle.cache.refresh(); diff --git a/packages/kbn-optimizer/src/run_optimizer.ts b/packages/kbn-optimizer/src/run_optimizer.ts index ab12cc679bc629..37260e942717b9 100644 --- a/packages/kbn-optimizer/src/run_optimizer.ts +++ b/packages/kbn-optimizer/src/run_optimizer.ts @@ -39,10 +39,26 @@ export type OptimizerUpdate = Update; export type OptimizerUpdate$ = Rx.Observable; export function runOptimizer(config: OptimizerConfig) { - return Rx.defer(async () => ({ - startTime: Date.now(), - cacheKey: await getOptimizerCacheKey(config), - })).pipe( + return Rx.defer(async () => { + if (process.platform === 'darwin') { + try { + require.resolve('fsevents'); + } catch (error) { + if (error.code === 'MODULE_NOT_FOUND') { + throw new Error( + '`fsevents` module is not installed, most likely because you need to follow the instructions at https://github.com/nodejs/node-gyp/blob/master/macOS_Catalina.md and re-bootstrap Kibana' + ); + } + + throw error; + } + } + + return { + startTime: Date.now(), + cacheKey: await getOptimizerCacheKey(config), + }; + }).pipe( mergeMap(({ startTime, cacheKey }) => { const bundleCacheEvent$ = getBundleCacheEvent$(config, cacheKey).pipe( observeOn(Rx.asyncScheduler), diff --git a/packages/kbn-optimizer/src/worker/run_compilers.ts b/packages/kbn-optimizer/src/worker/run_compilers.ts index 0dfce4b5addbad..4ab289d031d721 100644 --- a/packages/kbn-optimizer/src/worker/run_compilers.ts +++ b/packages/kbn-optimizer/src/worker/run_compilers.ts @@ -65,8 +65,8 @@ const observeCompiler = ( * Called by webpack as a single run compilation is starting */ const started$ = Rx.merge( - Rx.fromEventPattern(cb => beforeRun.tap(PLUGIN_NAME, cb)), - Rx.fromEventPattern(cb => watchRun.tap(PLUGIN_NAME, cb)) + Rx.fromEventPattern((cb) => beforeRun.tap(PLUGIN_NAME, cb)), + Rx.fromEventPattern((cb) => watchRun.tap(PLUGIN_NAME, cb)) ).pipe(mapTo(compilerMsgs.running())); /** @@ -74,8 +74,8 @@ const observeCompiler = ( * needAdditionalPass property is set then another compilation * is about to be started, so we shouldn't send complete quite yet */ - const complete$ = Rx.fromEventPattern(cb => done.tap(PLUGIN_NAME, cb)).pipe( - maybeMap(stats => { + const complete$ = Rx.fromEventPattern((cb) => done.tap(PLUGIN_NAME, cb)).pipe( + maybeMap((stats) => { // @ts-ignore not included in types, but it is real https://github.com/webpack/webpack/blob/ab4fa8ddb3f433d286653cd6af7e3aad51168649/lib/Watching.js#L58 if (stats.compilation.needAdditionalPass) { return undefined; @@ -134,7 +134,7 @@ const observeCompiler = ( ); } - const files = Array.from(referencedFiles).sort(ascending(p => p)); + const files = Array.from(referencedFiles).sort(ascending((p) => p)); const mtimes = new Map( files.map((path): [string, number | undefined] => { try { @@ -167,8 +167,10 @@ const observeCompiler = ( * prevets assets from being emitted, and prevents watching * from continuing. */ - const error$ = Rx.fromEventPattern(cb => compiler.hooks.failed.tap(PLUGIN_NAME, cb)).pipe( - map(error => { + const error$ = Rx.fromEventPattern((cb) => + compiler.hooks.failed.tap(PLUGIN_NAME, cb) + ).pipe( + map((error) => { throw compilerMsgs.error(error); }) ); @@ -184,7 +186,7 @@ const observeCompiler = ( * Run webpack compilers */ export const runCompilers = (workerConfig: WorkerConfig, bundles: Bundle[]) => { - const multiCompiler = webpack(bundles.map(def => getWebpackConfig(def, workerConfig))); + const multiCompiler = webpack(bundles.map((def) => getWebpackConfig(def, workerConfig))); return Rx.merge( /** diff --git a/packages/kbn-optimizer/src/worker/run_worker.ts b/packages/kbn-optimizer/src/worker/run_worker.ts index cbec4c3f44c7d8..f83c69477f4718 100644 --- a/packages/kbn-optimizer/src/worker/run_worker.ts +++ b/packages/kbn-optimizer/src/worker/run_worker.ts @@ -82,10 +82,10 @@ Rx.defer(() => { return runCompilers(workerConfig, bundles); }).subscribe( - msg => { + (msg) => { send(msg); }, - error => { + (error) => { if (isWorkerMsg(error)) { send(error); } else { diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index 6d6686a5bde1b9..5d02462ef1bb87 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -21,7 +21,7 @@ import webpack from 'webpack'; import { stringifyRequest } from 'loader-utils'; // eslint-disable-next-line import/no-default-export -export default function(this: webpack.loader.LoaderContext) { +export default function (this: webpack.loader.LoaderContext) { return ` if (window.__kbnDarkMode__) { require(${stringifyRequest(this, `${this.resourcePath}?dark`)}) diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 49bcc6e7e704c2..0c9a5b0a756877 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -64,7 +64,7 @@ function dynamicExternals(bundle: Bundle, context: string, request: string) { // ignore requests that don't include a /{dirname}/public for one of our // "static" bundles as a cheap way to avoid doing path resolution // for paths that couldn't possibly resolve to what we're looking for - const reqToStaticBundle = STATIC_BUNDLE_PLUGINS.some(p => + const reqToStaticBundle = STATIC_BUNDLE_PLUGINS.some((p) => request.includes(`/${p.dirname}/public`) ); if (!reqToStaticBundle) { @@ -100,7 +100,7 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) { output: { path: bundle.outputDir, filename: `[name].${bundle.type}.js`, - devtoolModuleFilenameTemplate: info => + devtoolModuleFilenameTemplate: (info) => `/${bundle.type}:${bundle.id}/${Path.relative( bundle.sourceRoot, info.absoluteResourcePath @@ -121,7 +121,7 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) { externals: [ UiSharedDeps.externals, - function(context, request, cb) { + function (context, request, cb) { try { cb(undefined, dynamicExternals(bundle, context, request)); } catch (error) { diff --git a/packages/kbn-plugin-generator/index.js b/packages/kbn-plugin-generator/index.js index 5f20569886d887..e61037e42d63f4 100644 --- a/packages/kbn-plugin-generator/index.js +++ b/packages/kbn-plugin-generator/index.js @@ -61,7 +61,7 @@ exports.run = function run(argv) { name, targetPath, }, - }).catch(error => { + }).catch((error) => { console.error(chalk`{red fatal error}!`); console.error(error.stack); process.exit(1); diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index 9073ce865a9637..7fc29b1e6bd0a0 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -59,7 +59,7 @@ async function eslintPlugin(dir) { } } -module.exports = function({ name, targetPath }) { +module.exports = function ({ name, targetPath }) { return { prompts: { customPath: { @@ -99,7 +99,7 @@ module.exports = function({ name, targetPath }) { }, generateTranslations: { type: 'confirm', - when: answers => { + when: (answers) => { // only for 3rd party plugins return !answers.customPath && answers.generateApp; }, @@ -112,7 +112,7 @@ module.exports = function({ name, targetPath }) { generateScss: { type: 'confirm', message: 'Should SCSS be used?', - when: answers => answers.generateApp, + when: (answers) => answers.generateApp, default: true, }, generateEslint: { @@ -135,7 +135,7 @@ module.exports = function({ name, targetPath }) { 'eslintrc.js': '.eslintrc.js', 'i18nrc.json': '.i18nrc.json', }, - data: answers => { + data: (answers) => { const pathToPlugin = answers.customPath ? resolve(answers.customPath, camelCase(name), 'public') : resolve(targetPath, 'public'); diff --git a/packages/kbn-plugin-helpers/bin/plugin-helpers.js b/packages/kbn-plugin-helpers/bin/plugin-helpers.js index 18a08332605ea5..175ff1019fa2dc 100755 --- a/packages/kbn-plugin-helpers/bin/plugin-helpers.js +++ b/packages/kbn-plugin-helpers/bin/plugin-helpers.js @@ -25,4 +25,4 @@ if (nodeMajorVersion < 6) { process.exit(1); } -require('../cli'); +require('../target/cli'); diff --git a/packages/kbn-plugin-helpers/lib/index.d.ts b/packages/kbn-plugin-helpers/lib/index.d.ts deleted file mode 100644 index 6f1eb73505b05e..00000000000000 --- a/packages/kbn-plugin-helpers/lib/index.d.ts +++ /dev/null @@ -1,26 +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. - */ - -export function babelRegister(): void; -export function resolveKibanaPath(path: string): string; -export function readFtrConfigFile(path: string): any; -export function run( - task: 'build' | 'start' | 'testAll' | 'testKarma' | 'testMocha' | 'postinstall', - options: any -): Promise; diff --git a/packages/kbn-plugin-helpers/lib/run.test.js b/packages/kbn-plugin-helpers/lib/run.test.js deleted file mode 100644 index 4c87399319b3bb..00000000000000 --- a/packages/kbn-plugin-helpers/lib/run.test.js +++ /dev/null @@ -1,58 +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. - */ - -/*eslint-env jest*/ - -jest.mock('./plugin_config', () => () => ({ id: 'testPlugin' })); - -jest.mock('./tasks', () => { - return { testTask: jest.fn() }; -}); - -const run = require('./run'); - -describe('lib/run', () => { - beforeEach(() => jest.resetAllMocks()); - - it('throw given an invalid task', function() { - const invalidTaskName = 'thisisnotavalidtasknameandneverwillbe'; - const runner = () => run(invalidTaskName); - - expect(runner).toThrow(/invalid task/i); - }); - - it('runs specified task with plugin and runner', function() { - run('testTask'); - - const { testTask } = require('./tasks'); - const plugin = require('./plugin_config')(); - const args = testTask.mock.calls[0]; - expect(testTask.mock.calls).toHaveLength(1); - expect(args[0]).toEqual(plugin); - expect(args[1]).toBe(run); - }); - - it('returns value returned by task', function() { - const { testTask } = require('./tasks'); - - const symbol = Symbol('foo'); - testTask.mockReturnValue(symbol); - expect(run('testTask')).toBe(symbol); - }); -}); diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index 53c998ddfaac24..040b779a699519 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -1,17 +1,16 @@ { "name": "@kbn/plugin-helpers", - "private": true, "version": "9.0.2", + "private": true, "description": "Just some helpers for kibana plugin devs.", - "main": "lib/index.js", + "license": "Apache-2.0", + "main": "target/lib/index.js", + "scripts": { + "kbn:bootstrap": "tsc" + }, "bin": { "plugin-helpers": "bin/plugin-helpers.js" }, - "author": "Spencer Alger ", - "license": "Apache-2.0", - "peerDependencies": { - "@kbn/babel-preset": "1.0.0" - }, "dependencies": { "@babel/core": "^7.9.0", "argv-split": "^2.0.1", @@ -27,6 +26,20 @@ "node-sass": "^4.13.1", "through2": "^2.0.3", "through2-map": "^3.0.0", + "vinyl": "^2.2.0", "vinyl-fs": "^3.0.3" + }, + "devDependencies": { + "@types/gulp-rename": "^0.0.33", + "@types/gulp-zip": "^4.0.1", + "@types/inquirer": "^6.5.0", + "@types/node-sass": "^4.11.0", + "@types/through2": "^2.0.35", + "@types/through2-map": "^3.0.0", + "@types/vinyl": "^2.0.4", + "typescript": "3.7.2" + }, + "peerDependencies": { + "@kbn/babel-preset": "1.0.0" } } diff --git a/packages/kbn-plugin-helpers/cli.js b/packages/kbn-plugin-helpers/src/cli.ts similarity index 84% rename from packages/kbn-plugin-helpers/cli.js rename to packages/kbn-plugin-helpers/src/cli.ts index 48b70535272fe8..b894f854a484ff 100644 --- a/packages/kbn-plugin-helpers/cli.js +++ b/packages/kbn-plugin-helpers/src/cli.ts @@ -17,13 +17,16 @@ * under the License. */ -const program = require('commander'); +import Fs from 'fs'; +import Path from 'path'; -const pkg = require('./package.json'); -const createCommanderAction = require('./lib/commander_action'); -const docs = require('./lib/docs'); -const enableCollectingUnknownOptions = require('./lib/enable_collecting_unknown_options'); +import program from 'commander'; +import { createCommanderAction } from './lib/commander_action'; +import { docs } from './lib/docs'; +import { enableCollectingUnknownOptions } from './lib/enable_collecting_unknown_options'; + +const pkg = JSON.parse(Fs.readFileSync(Path.resolve(__dirname, '../package.json'), 'utf8')); program.version(pkg.version); enableCollectingUnknownOptions( @@ -32,7 +35,7 @@ enableCollectingUnknownOptions( .description('Start kibana and have it include this plugin') .on('--help', docs('start')) .action( - createCommanderAction('start', command => ({ + createCommanderAction('start', (command) => ({ flags: command.unknownOptions, })) ) @@ -55,7 +58,7 @@ program buildVersion: command.buildVersion, kibanaVersion: command.kibanaVersion, skipArchive: Boolean(command.skipArchive), - files: files, + files, })) ); @@ -72,7 +75,7 @@ program .option('-p, --plugins ', "Manually specify which plugins' test bundles to run") .on('--help', docs('test/karma')) .action( - createCommanderAction('testKarma', command => ({ + createCommanderAction('testKarma', (command) => ({ dev: Boolean(command.dev), plugins: command.plugins, })) @@ -84,7 +87,7 @@ program .on('--help', docs('test/mocha')) .action( createCommanderAction('testMocha', (command, files) => ({ - files: files, + files, })) ); diff --git a/packages/kbn-plugin-helpers/lib/__snapshots__/commander_action.test.js.snap b/packages/kbn-plugin-helpers/src/lib/__snapshots__/commander_action.test.js.snap similarity index 100% rename from packages/kbn-plugin-helpers/lib/__snapshots__/commander_action.test.js.snap rename to packages/kbn-plugin-helpers/src/lib/__snapshots__/commander_action.test.js.snap diff --git a/packages/kbn-plugin-helpers/lib/commander_action.test.js b/packages/kbn-plugin-helpers/src/lib/commander_action.test.js similarity index 94% rename from packages/kbn-plugin-helpers/lib/commander_action.test.js rename to packages/kbn-plugin-helpers/src/lib/commander_action.test.js index 40ac6755f02e54..501c0bd0619130 100644 --- a/packages/kbn-plugin-helpers/lib/commander_action.test.js +++ b/packages/kbn-plugin-helpers/src/lib/commander_action.test.js @@ -17,12 +17,10 @@ * under the License. */ -/*eslint-env jest*/ +import { createCommanderAction } from './commander_action'; +import { run } from './run'; -const createCommanderAction = require('./commander_action'); -const run = require('./run'); - -jest.mock('./run', () => jest.fn()); +jest.mock('./run'); const STACK_TRACE_RE = /\n(?:\s+at .+(?:\n|$))+/g; expect.addSnapshotSerializer({ diff --git a/packages/kbn-plugin-helpers/lib/commander_action.js b/packages/kbn-plugin-helpers/src/lib/commander_action.ts similarity index 81% rename from packages/kbn-plugin-helpers/lib/commander_action.js rename to packages/kbn-plugin-helpers/src/lib/commander_action.ts index 497dee8edf740d..ce585dd0a02c88 100644 --- a/packages/kbn-plugin-helpers/lib/commander_action.js +++ b/packages/kbn-plugin-helpers/src/lib/commander_action.ts @@ -17,10 +17,13 @@ * under the License. */ -const run = require('./run'); +import { run } from './run'; +import { Tasks } from './tasks'; -module.exports = function createCommanderAction(taskName, getOptions = () => {}) { - return async (...args) => { +type GetOptions = (command: any, ...args: string[]) => any; + +export function createCommanderAction(taskName: keyof Tasks, getOptions: GetOptions = () => {}) { + return async (...args: string[]) => { try { // command is the last arg passed by commander, but we move it to the front of the list const command = args.pop(); @@ -30,4 +33,4 @@ module.exports = function createCommanderAction(taskName, getOptions = () => {}) process.exit(1); } }; -}; +} diff --git a/packages/kbn-plugin-helpers/lib/config_file.js b/packages/kbn-plugin-helpers/src/lib/config_file.ts similarity index 70% rename from packages/kbn-plugin-helpers/lib/config_file.js rename to packages/kbn-plugin-helpers/src/lib/config_file.ts index 5b8be836998e44..1566932b658722 100644 --- a/packages/kbn-plugin-helpers/lib/config_file.js +++ b/packages/kbn-plugin-helpers/src/lib/config_file.ts @@ -17,33 +17,34 @@ * under the License. */ -const resolve = require('path').resolve; -const readFileSync = require('fs').readFileSync; +import { resolve } from 'path'; +import { readFileSync } from 'fs'; -const configFiles = ['.kibana-plugin-helpers.json', '.kibana-plugin-helpers.dev.json']; -const configCache = {}; +const configFileNames = ['.kibana-plugin-helpers.json', '.kibana-plugin-helpers.dev.json']; -module.exports = function(root) { - if (!root) root = process.cwd(); +interface Config { + [key: string]: unknown; +} - if (configCache[root]) { - return configCache[root]; +const configCache = new Map(); + +export function configFile(root: string = process.cwd()) { + if (configCache.has(root)) { + return configCache.get(root)!; } // config files to read from, in the order they are merged together - let config = (configCache[root] = {}); - - configFiles.forEach(function(configFile) { + let config: Config = {}; + for (const name of configFileNames) { try { - const content = JSON.parse(readFileSync(resolve(root, configFile))); - config = Object.assign(config, content); + config = JSON.parse(readFileSync(resolve(root, name), 'utf8')); } catch (e) { // rethrow error unless it's complaining about file not existing if (e.code !== 'ENOENT') { throw e; } } - }); + } const deprecationMsg = 'has been removed from `@kbn/plugin-helpers`. ' + @@ -59,8 +60,10 @@ module.exports = function(root) { } // use resolve to ensure correct resolution of paths - const { includePlugins } = config; - if (includePlugins) config.includePlugins = includePlugins.map(path => resolve(root, path)); + if (Array.isArray(config.includePlugins)) { + config.includePlugins = config.includePlugins.map((path: string) => resolve(root, path)); + } + configCache.set(root, config); return config; -}; +} diff --git a/packages/kbn-plugin-helpers/lib/docs.js b/packages/kbn-plugin-helpers/src/lib/docs.ts similarity index 71% rename from packages/kbn-plugin-helpers/lib/docs.js rename to packages/kbn-plugin-helpers/src/lib/docs.ts index f1b288c68c390e..fb05fd0c5c2ce0 100644 --- a/packages/kbn-plugin-helpers/lib/docs.js +++ b/packages/kbn-plugin-helpers/src/lib/docs.ts @@ -17,21 +17,19 @@ * under the License. */ -const resolve = require('path').resolve; -const readFileSync = require('fs').readFileSync; +import { resolve } from 'path'; +import { readFileSync } from 'fs'; -function indent(txt, n) { +function indent(txt: string, n: number) { const space = new Array(n + 1).join(' '); return space + txt.split('\n').join('\n' + space); } -module.exports = function docs(name) { - const md = readFileSync(resolve(__dirname, '../tasks', name, 'README.md'), 'utf8'); +export function docs(name: string) { + const md = readFileSync(resolve(__dirname, '../../src/tasks', name, 'README.md'), 'utf8'); - return function() { - console.log('\n Docs:'); - console.log(''); - console.log(indent(md, 4)); - console.log(''); + return function () { + /* eslint-disable-next-line no-console */ + console.log(`\n Docs:\n\n${indent(md, 4)}\n\n`); }; -}; +} diff --git a/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js b/packages/kbn-plugin-helpers/src/lib/enable_collecting_unknown_options.ts similarity index 85% rename from packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js rename to packages/kbn-plugin-helpers/src/lib/enable_collecting_unknown_options.ts index 8b855a8b8769d2..0d692aed063051 100644 --- a/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js +++ b/packages/kbn-plugin-helpers/src/lib/enable_collecting_unknown_options.ts @@ -17,12 +17,14 @@ * under the License. */ -module.exports = function enableCollectingUnknownOptions(command) { +import { Command } from 'commander'; + +export function enableCollectingUnknownOptions(command: Command) { const origParse = command.parseOptions; command.allowUnknownOption(); - command.parseOptions = function(argv) { + command.parseOptions = function (argv: string[]) { const opts = origParse.call(this, argv); this.unknownOptions = opts.unknown; return opts; }; -}; +} diff --git a/packages/kbn-plugin-helpers/src/lib/index.ts b/packages/kbn-plugin-helpers/src/lib/index.ts new file mode 100644 index 00000000000000..acc7134308bec3 --- /dev/null +++ b/packages/kbn-plugin-helpers/src/lib/index.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 * from './run'; +export * from './utils'; +export * from './win_cmd'; +export * from './plugin_config'; +export * from './pipeline'; diff --git a/packages/kbn-plugin-helpers/src/lib/pipeline.ts b/packages/kbn-plugin-helpers/src/lib/pipeline.ts new file mode 100644 index 00000000000000..d66e18f5239a90 --- /dev/null +++ b/packages/kbn-plugin-helpers/src/lib/pipeline.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. + */ + +import Stream from 'stream'; +import Util from 'util'; + +export const pipeline = Util.promisify(Stream.pipeline); diff --git a/packages/kbn-plugin-helpers/lib/plugin_config.js b/packages/kbn-plugin-helpers/src/lib/plugin_config.ts similarity index 64% rename from packages/kbn-plugin-helpers/lib/plugin_config.js rename to packages/kbn-plugin-helpers/src/lib/plugin_config.ts index 60baa7fc976607..dc3ef936e2164e 100644 --- a/packages/kbn-plugin-helpers/lib/plugin_config.js +++ b/packages/kbn-plugin-helpers/src/lib/plugin_config.ts @@ -17,16 +17,26 @@ * under the License. */ -const resolve = require('path').resolve; -const readFileSync = require('fs').readFileSync; -const configFile = require('./config_file'); +import { resolve } from 'path'; +import { readFileSync } from 'fs'; -module.exports = function(root) { - if (!root) root = process.cwd(); +import { configFile } from './config_file'; +export interface PluginConfig { + root: string; + kibanaRoot: string; + serverTestPatterns: string[]; + buildSourcePatterns: string[]; + skipInstallDependencies: boolean; + id: string; + version: string; + pkg: any; + [k: string]: unknown; +} + +export function pluginConfig(root: string = process.cwd()): PluginConfig { const pluginPackageJsonPath = resolve(root, 'package.json'); - const pkg = JSON.parse(readFileSync(pluginPackageJsonPath)); - const config = configFile(root); + const pkg = JSON.parse(readFileSync(pluginPackageJsonPath, 'utf8')); const buildSourcePatterns = [ 'yarn.lock', @@ -42,6 +52,7 @@ module.exports = function(root) { const isPluginXpack = pkg.name === 'x-pack'; if (isPluginOnKibanaExtra && !isPluginXpack) { + // eslint-disable-next-line no-console console.warn( `In the future we will disable ../kibana-extra/{pluginName}. You should move your plugin ${pkg.name} as soon as possible to ./plugins/{pluginName}` ); @@ -49,17 +60,15 @@ module.exports = function(root) { const kibanaRootWhenNotXpackPlugin = isPluginOnKibanaExtra ? kibanaExtraDir : kibanaPluginsDir; - return Object.assign( - { - root: root, - kibanaRoot: isPluginXpack ? resolve(root, '..') : kibanaRootWhenNotXpackPlugin, - serverTestPatterns: ['server/**/__tests__/**/*.js'], - buildSourcePatterns: buildSourcePatterns, - skipInstallDependencies: false, - id: pkg.name, - pkg: pkg, - version: pkg.version, - }, - config - ); -}; + return { + root, + kibanaRoot: isPluginXpack ? resolve(root, '..') : kibanaRootWhenNotXpackPlugin, + serverTestPatterns: ['server/**/__tests__/**/*.js'], + buildSourcePatterns, + skipInstallDependencies: false, + id: pkg.name as string, + version: pkg.version as string, + pkg, + ...configFile(root), + }; +} diff --git a/packages/kbn-plugin-helpers/lib/run.js b/packages/kbn-plugin-helpers/src/lib/run.ts similarity index 75% rename from packages/kbn-plugin-helpers/lib/run.js rename to packages/kbn-plugin-helpers/src/lib/run.ts index 119b64f71e2f95..2b1a2a63c1074e 100644 --- a/packages/kbn-plugin-helpers/lib/run.js +++ b/packages/kbn-plugin-helpers/src/lib/run.ts @@ -17,15 +17,21 @@ * under the License. */ -const pluginConfig = require('./plugin_config'); -const tasks = require('./tasks'); +import { pluginConfig, PluginConfig } from './plugin_config'; +import { tasks, Tasks } from './tasks'; -module.exports = function run(name, options) { +export interface TaskContext { + plugin: PluginConfig; + run: typeof run; + options?: any; +} + +export function run(name: keyof Tasks, options?: any) { const action = tasks[name]; if (!action) { throw new Error('Invalid task: "' + name + '"'); } const plugin = pluginConfig(); - return action(plugin, run, options); -}; + return action({ plugin, run, options }); +} diff --git a/packages/kbn-plugin-helpers/lib/tasks.js b/packages/kbn-plugin-helpers/src/lib/tasks.ts similarity index 64% rename from packages/kbn-plugin-helpers/lib/tasks.js rename to packages/kbn-plugin-helpers/src/lib/tasks.ts index afc9c056d51d70..7817838760a2e1 100644 --- a/packages/kbn-plugin-helpers/lib/tasks.js +++ b/packages/kbn-plugin-helpers/src/lib/tasks.ts @@ -17,13 +17,22 @@ * under the License. */ -const buildTask = require('../tasks/build'); -const startTask = require('../tasks/start'); -const testAllTask = require('../tasks/test/all'); -const testKarmaTask = require('../tasks/test/karma'); -const testMochaTask = require('../tasks/test/mocha'); +import { buildTask } from '../tasks/build'; +import { startTask } from '../tasks/start'; +import { testAllTask } from '../tasks/test/all'; +import { testKarmaTask } from '../tasks/test/karma'; +import { testMochaTask } from '../tasks/test/mocha'; -module.exports = { +// define a tasks interface that we can extend in the tests +export interface Tasks { + build: typeof buildTask; + start: typeof startTask; + testAll: typeof testAllTask; + testKarma: typeof testKarmaTask; + testMocha: typeof testMochaTask; +} + +export const tasks: Tasks = { build: buildTask, start: startTask, testAll: testAllTask, diff --git a/packages/kbn-plugin-helpers/lib/utils.js b/packages/kbn-plugin-helpers/src/lib/utils.ts similarity index 74% rename from packages/kbn-plugin-helpers/lib/utils.js rename to packages/kbn-plugin-helpers/src/lib/utils.ts index 6e3d8969802a45..0348f9f8deda98 100644 --- a/packages/kbn-plugin-helpers/lib/utils.js +++ b/packages/kbn-plugin-helpers/src/lib/utils.ts @@ -17,11 +17,11 @@ * under the License. */ -const resolve = require('path').resolve; +import { resolve } from 'path'; -const pluginConfig = require('./plugin_config'); +import { pluginConfig } from './plugin_config'; -function babelRegister() { +export function babelRegister() { const plugin = pluginConfig(); try { @@ -36,18 +36,7 @@ function babelRegister() { } } -function resolveKibanaPath(path) { +export function resolveKibanaPath(path: string) { const plugin = pluginConfig(); return resolve(plugin.kibanaRoot, path); } - -function readFtrConfigFile(log, path, settingOverrides) { - return require('@kbn/test') // eslint-disable-line import/no-dynamic-require - .readConfigFile(log, path, settingOverrides); -} - -module.exports = { - babelRegister: babelRegister, - resolveKibanaPath: resolveKibanaPath, - readFtrConfigFile: readFtrConfigFile, -}; diff --git a/packages/kbn-plugin-helpers/src/lib/win_cmd.ts b/packages/kbn-plugin-helpers/src/lib/win_cmd.ts new file mode 100644 index 00000000000000..a3f5d144602ed5 --- /dev/null +++ b/packages/kbn-plugin-helpers/src/lib/win_cmd.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. + */ + +import Os from 'os'; + +export function winCmd(cmd: string) { + return /^win/.test(Os.platform()) ? cmd + '.cmd' : cmd; +} diff --git a/packages/kbn-plugin-helpers/tasks/build/README.md b/packages/kbn-plugin-helpers/src/tasks/build/README.md similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/README.md rename to packages/kbn-plugin-helpers/src/tasks/build/README.md diff --git a/packages/kbn-plugin-helpers/tasks/build/build_action.js b/packages/kbn-plugin-helpers/src/tasks/build/build_task.ts similarity index 57% rename from packages/kbn-plugin-helpers/tasks/build/build_action.js rename to packages/kbn-plugin-helpers/src/tasks/build/build_task.ts index 32513958f66abb..16207f323ff71b 100644 --- a/packages/kbn-plugin-helpers/tasks/build/build_action.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/build_task.ts @@ -17,15 +17,14 @@ * under the License. */ -const join = require('path').join; -const resolve = require('path').resolve; -const inquirer = require('inquirer'); +import { join, resolve } from 'path'; +import inquirer from 'inquirer'; -const createBuild = require('./create_build'); -const createPackage = require('./create_package'); +import { TaskContext } from '../../lib'; +import { createBuild } from './create_build'; +import { createPackage } from './create_package'; -module.exports = function(plugin, run, options) { - options = options || {}; +export async function buildTask({ plugin, options = {} }: TaskContext) { let buildVersion = plugin.version; let kibanaVersion = (plugin.pkg.kibana && plugin.pkg.kibana.version) || plugin.pkg.version; let buildFiles = plugin.buildSourcePatterns; @@ -41,31 +40,24 @@ module.exports = function(plugin, run, options) { if (options.buildVersion) buildVersion = options.buildVersion; if (options.kibanaVersion) kibanaVersion = options.kibanaVersion; - let buildStep; - if (kibanaVersion === 'kibana') { - buildStep = askForKibanaVersion().then(function(customKibanaVersion) { - return createBuild(plugin, buildTarget, buildVersion, customKibanaVersion, buildFiles); - }); - } else { - buildStep = createBuild(plugin, buildTarget, buildVersion, kibanaVersion, buildFiles); + const chosenKibanaVersion = + kibanaVersion === 'kibana' ? await askForKibanaVersion() : kibanaVersion; + + await createBuild(plugin, buildTarget, buildVersion, chosenKibanaVersion, buildFiles); + + if (!options.skipArchive) { + await createPackage(plugin, buildTarget, buildVersion); } +} - return buildStep.then(function() { - if (options.skipArchive) return; - return createPackage(plugin, buildTarget, buildVersion); - }); -}; +async function askForKibanaVersion() { + const answers = await inquirer.prompt([ + { + type: 'input', + name: 'kibanaVersion', + message: 'What version of Kibana are you building for?', + }, + ]); -function askForKibanaVersion() { - return inquirer - .prompt([ - { - type: 'input', - name: 'kibanaVersion', - message: 'What version of Kibana are you building for?', - }, - ]) - .then(function(answers) { - return answers.kibanaVersion; - }); + return answers.kibanaVersion; } diff --git a/packages/kbn-plugin-helpers/src/tasks/build/create_build.ts b/packages/kbn-plugin-helpers/src/tasks/build/create_build.ts new file mode 100644 index 00000000000000..a469e4fe673908 --- /dev/null +++ b/packages/kbn-plugin-helpers/src/tasks/build/create_build.ts @@ -0,0 +1,196 @@ +/* + * 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 { relative } from 'path'; +import path from 'path'; + +import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs'; +import execa from 'execa'; +import sass from 'node-sass'; +import del from 'del'; +import File from 'vinyl'; +import vfs from 'vinyl-fs'; +import rename from 'gulp-rename'; +import through from 'through2'; +import minimatch from 'minimatch'; +// @ts-ignore +import gulpBabel from 'gulp-babel'; + +import { PluginConfig, winCmd, pipeline } from '../../lib'; +import { rewritePackageJson } from './rewrite_package_json'; + +// `link:` dependencies create symlinks, but we don't want to include symlinks +// in the built zip file. Therefore we remove all symlinked dependencies, so we +// can re-create them when installing the plugin. +function removeSymlinkDependencies(root: string) { + const nodeModulesPattern = path.join(root, '**', 'node_modules', '**'); + + return through.obj((file: File, _, cb) => { + const isSymlink = file.symlink != null; + const isDependency = minimatch(file.path, nodeModulesPattern); + + if (isSymlink && isDependency) { + unlinkSync(file.path); + } + + cb(); + }); +} + +// parse a ts config file +function parseTsconfig(pluginSourcePath: string, configPath: string) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const ts = require(path.join(pluginSourcePath, 'node_modules', 'typescript')); + + const { error, config } = ts.parseConfigFileTextToJson( + configPath, + readFileSync(configPath, 'utf8') + ); + + if (error) { + throw error; + } + + return config; +} + +// transpile with babel +async function transpileWithBabel(srcGlobs: string[], buildRoot: string, presets: string[]) { + await pipeline( + vfs.src( + srcGlobs.concat([ + '!**/*.d.ts', + '!**/*.{test,test.mocks,mock,mocks}.{ts,tsx}', + '!**/node_modules/**', + '!**/bower_components/**', + '!**/__tests__/**', + ]), + { + cwd: buildRoot, + } + ), + + gulpBabel({ + babelrc: false, + presets, + }), + + vfs.dest(buildRoot) + ); +} + +export async function createBuild( + plugin: PluginConfig, + buildTarget: string, + buildVersion: string, + kibanaVersion: string, + files: string[] +) { + const buildSource = plugin.root; + const buildRoot = path.join(buildTarget, 'kibana', plugin.id); + + await del(buildTarget); + + // copy source files and apply some transformations in the process + await pipeline( + vfs.src(files, { + cwd: buildSource, + base: buildSource, + allowEmpty: true, + }), + + // modify the package.json file + rewritePackageJson(buildSource, buildVersion, kibanaVersion), + + // put all files inside the correct directories + rename(function nestFileInDir(filePath) { + const nonRelativeDirname = filePath.dirname!.replace(/^(\.\.\/?)+/g, ''); + filePath.dirname = path.join(relative(buildTarget, buildRoot), nonRelativeDirname); + }), + + // write files back to disk + vfs.dest(buildTarget) + ); + + // install packages in build + if (!plugin.skipInstallDependencies) { + execa.sync(winCmd('yarn'), ['install', '--production', '--pure-lockfile'], { + cwd: buildRoot, + }); + } + + // compile stylesheet + if (typeof plugin.styleSheetToCompile === 'string') { + const file = path.resolve(plugin.root, plugin.styleSheetToCompile); + if (!existsSync(file)) { + throw new Error(`Path provided for styleSheetToCompile does not exist: ${file}`); + } + + const outputFileName = path.basename(file, path.extname(file)) + '.css'; + const output = path.join(buildRoot, path.dirname(plugin.styleSheetToCompile), outputFileName); + + const rendered = sass.renderSync({ file, output }); + writeFileSync(output, rendered.css); + + del.sync([path.join(buildRoot, '**', '*.s{a,c}ss')]); + } + + // transform typescript to js and clean out typescript + const tsConfigPath = path.join(buildRoot, 'tsconfig.json'); + if (existsSync(tsConfigPath)) { + // attempt to patch the extends path in the tsconfig file + const buildConfig = parseTsconfig(buildSource, tsConfigPath); + + if (buildConfig.extends) { + buildConfig.extends = path.join(relative(buildRoot, buildSource), buildConfig.extends); + + writeFileSync(tsConfigPath, JSON.stringify(buildConfig)); + } + + // Transpile ts server code + // + // Include everything except content from public folders + await transpileWithBabel(['**/*.{ts,tsx}', '!**/public/**'], buildRoot, [ + require.resolve('@kbn/babel-preset/node_preset'), + ]); + + // Transpile ts client code + // + // Include everything inside a public directory + await transpileWithBabel(['**/public/**/*.{ts,tsx}'], buildRoot, [ + require.resolve('@kbn/babel-preset/webpack_preset'), + ]); + + del.sync([ + path.join(buildRoot, '**', '*.{ts,tsx,d.ts}'), + path.join(buildRoot, 'tsconfig.json'), + ]); + } + + // remove symlinked dependencies + await pipeline( + vfs.src([relative(buildTarget, buildRoot) + '/**/*'], { + cwd: buildTarget, + base: buildTarget, + resolveSymlinks: false, + }), + + removeSymlinkDependencies(buildRoot) + ); +} diff --git a/packages/kbn-plugin-helpers/tasks/build/create_package.js b/packages/kbn-plugin-helpers/src/tasks/build/create_package.ts similarity index 58% rename from packages/kbn-plugin-helpers/tasks/build/create_package.js rename to packages/kbn-plugin-helpers/src/tasks/build/create_package.ts index 6df55fda902b04..9fa2305a94eabc 100644 --- a/packages/kbn-plugin-helpers/tasks/build/create_package.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/create_package.ts @@ -17,28 +17,30 @@ * under the License. */ -const join = require('path').join; -const relative = require('path').relative; -const del = require('del'); -const vfs = require('vinyl-fs'); -const zip = require('gulp-zip'); +import { relative, join } from 'path'; -module.exports = function createPackage(plugin, buildTarget, buildVersion) { +import del from 'del'; +import vfs from 'vinyl-fs'; +import zip from 'gulp-zip'; + +import { pipeline, PluginConfig } from '../../lib'; + +export async function createPackage( + plugin: PluginConfig, + buildTarget: string, + buildVersion: string +) { const buildId = `${plugin.id}-${buildVersion}`; const buildRoot = join(buildTarget, 'kibana', plugin.id); + const buildFiles = [relative(buildTarget, buildRoot) + '/**/*']; // zip up the package - return new Promise(function(resolve, reject) { - const buildFiles = [relative(buildTarget, buildRoot) + '/**/*']; + await pipeline( + vfs.src(buildFiles, { cwd: buildTarget, base: buildTarget }), + zip(`${buildId}.zip`), + vfs.dest(buildTarget) + ); - vfs - .src(buildFiles, { cwd: buildTarget, base: buildTarget }) - .pipe(zip(`${buildId}.zip`)) - .pipe(vfs.dest(buildTarget)) - .on('end', resolve) - .on('error', reject); - }).then(function() { - // clean up the build path - return del(join(buildTarget, 'kibana')); - }); -}; + // clean up the build path + await del(join(buildTarget, 'kibana')); +} diff --git a/packages/kbn-plugin-helpers/tasks/build/git_info.js b/packages/kbn-plugin-helpers/src/tasks/build/git_info.ts similarity index 92% rename from packages/kbn-plugin-helpers/tasks/build/git_info.js rename to packages/kbn-plugin-helpers/src/tasks/build/git_info.ts index 655b5c95a01025..e3a68f82e48b29 100644 --- a/packages/kbn-plugin-helpers/tasks/build/git_info.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/git_info.ts @@ -17,16 +17,18 @@ * under the License. */ -const execFileSync = require('child_process').execFileSync; +import { execFileSync } from 'child_process'; -module.exports = function gitInfo(rootPath) { +export function gitInfo(rootPath: string) { try { const LOG_SEPARATOR = '||'; + const commitCount = execFileSync('git', ['rev-list', '--count', 'HEAD'], { cwd: rootPath, stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', }); + const logLine = execFileSync('git', ['log', '--pretty=%h' + LOG_SEPARATOR + '%cD', '-n', '1'], { cwd: rootPath, stdio: ['ignore', 'pipe', 'ignore'], @@ -41,4 +43,4 @@ module.exports = function gitInfo(rootPath) { } catch (e) { return {}; } -}; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index.js b/packages/kbn-plugin-helpers/src/tasks/build/index.ts similarity index 96% rename from src/legacy/core_plugins/kibana/public/management/sections/index.js rename to packages/kbn-plugin-helpers/src/tasks/build/index.ts index adc1741f57263a..d22d544a954915 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/index.ts @@ -17,4 +17,4 @@ * under the License. */ -import './index_patterns'; +export * from './build_task'; diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js similarity index 96% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js index c2d2ade5687615..052d224b662e25 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js @@ -17,7 +17,7 @@ * under the License. */ -module.exports = kibana => +module.exports = (kibana) => new kibana.Plugin({ uiExports: { hacks: ['plugins/test_plugin/hack.js'], diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/package.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/package.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/package.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/package.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/public/hack.js similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/public/hack.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/public/hack.js diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/translations/es.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/translations/es.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/translations/es.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/translations/es.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js similarity index 96% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js index c2d2ade5687615..052d224b662e25 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/build_action_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js @@ -17,7 +17,7 @@ * under the License. */ -module.exports = kibana => +module.exports = (kibana) => new kibana.Plugin({ uiExports: { hacks: ['plugins/test_plugin/hack.js'], diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/package.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/package.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/package.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/package.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/hack.js similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/hack.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/hack.js diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/styles.scss b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/styles.scss similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/styles.scss rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/public/styles.scss diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/translations/es.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/translations/es.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/translations/es.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/translations/es.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js similarity index 96% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js index c2d2ade5687615..052d224b662e25 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_build_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/index.js @@ -17,7 +17,7 @@ * under the License. */ -module.exports = kibana => +module.exports = (kibana) => new kibana.Plugin({ uiExports: { hacks: ['plugins/test_plugin/hack.js'], diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/package.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/package.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/package.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/package.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/public/hack.js similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/public/hack.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/public/hack.js diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/translations/es.json b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/translations/es.json similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/translations/es.json rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__fixtures__/create_package_test_plugin/translations/es.json diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/__snapshots__/build_action.test.js.snap b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__snapshots__/build_action.test.js.snap similarity index 100% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/__snapshots__/build_action.test.js.snap rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/__snapshots__/build_action.test.js.snap diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/build_action.test.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/build_action.test.js similarity index 72% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/build_action.test.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/build_action.test.js index 90deb0c4ac4a86..d9f20129e85f9e 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/build_action.test.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/build_action.test.js @@ -17,34 +17,34 @@ * under the License. */ -const resolve = require('path').resolve; -const fs = require('fs'); -const del = require('del'); +import { resolve } from 'path'; +import fs from 'fs'; +import del from 'del'; +import { pluginConfig } from '../../../lib'; const PLUGIN_FIXTURE = resolve(__dirname, '__fixtures__/build_action_test_plugin'); const PLUGIN_BUILD_DIR = resolve(PLUGIN_FIXTURE, 'build'); -const PLUGIN = require('../../../lib/plugin_config')(PLUGIN_FIXTURE); -const noop = () => {}; +const plugin = pluginConfig(PLUGIN_FIXTURE); describe('creating build zip', () => { - const buildAction = require('../build_action'); + const { buildTask } = require('../build_task'); beforeEach(() => del(PLUGIN_BUILD_DIR)); afterEach(() => del(PLUGIN_BUILD_DIR)); it('creates a zip in the build directory', async () => { - await buildAction(PLUGIN); + await buildTask({ plugin }); - const buildFile = resolve(PLUGIN_BUILD_DIR, PLUGIN.id + '-' + PLUGIN.version + '.zip'); + const buildFile = resolve(PLUGIN_BUILD_DIR, plugin.id + '-' + plugin.version + '.zip'); if (!fs.existsSync(buildFile)) { throw new Error('Build file not found: ' + buildFile); } }); it('skips zip creation based on flag', async () => { - await buildAction(PLUGIN, noop, { skipArchive: true }); + await buildTask({ plugin, options: { skipArchive: true } }); - const buildFile = resolve(PLUGIN_BUILD_DIR, PLUGIN.id + '-' + PLUGIN.version + '.zip'); + const buildFile = resolve(PLUGIN_BUILD_DIR, plugin.id + '-' + plugin.version + '.zip'); if (fs.existsSync(buildFile)) { throw new Error('Build file not found: ' + buildFile); } @@ -53,13 +53,13 @@ describe('creating build zip', () => { describe('calling create_build', () => { let mockBuild; - let buildAction; + let buildTask; beforeEach(() => { jest.resetModules(); - mockBuild = jest.fn(() => Promise.resolve()); - jest.mock('../create_build', () => mockBuild); - buildAction = require('../build_action'); + jest.mock('../create_build'); + ({ createBuild: mockBuild } = require('../create_build')); + ({ buildTask } = require('../build_task')); }); const nameArgs = ([plugin, buildTarget, buildVersion, kibanaVersion, files]) => ({ @@ -76,7 +76,7 @@ describe('calling create_build', () => { kibanaVersion: '4.5.6', }; - await buildAction(PLUGIN, noop, options); + await buildTask({ plugin, options }); expect(mockBuild.mock.calls).toHaveLength(1); @@ -86,12 +86,12 @@ describe('calling create_build', () => { }); it('uses default file list without files option', async () => { - await buildAction(PLUGIN); + await buildTask({ plugin }); expect(mockBuild.mock.calls).toHaveLength(1); const { files } = nameArgs(mockBuild.mock.calls[0]); - PLUGIN.buildSourcePatterns.forEach(file => expect(files).toContain(file)); + plugin.buildSourcePatterns.forEach((file) => expect(files).toContain(file)); }); it('uses only files passed in', async () => { @@ -99,12 +99,12 @@ describe('calling create_build', () => { files: ['index.js', 'LICENSE.txt', 'plugins/**/*', '{server,public}/**/*'], }; - await buildAction(PLUGIN, noop, options); + await buildTask({ plugin, options }); expect(mockBuild.mock.calls).toHaveLength(1); const { files } = nameArgs(mockBuild.mock.calls[0]); - options.files.forEach(file => expect(files).toContain(file)); + options.files.forEach((file) => expect(files).toContain(file)); }); it('rejects returned promise when build fails', async () => { @@ -112,6 +112,6 @@ describe('calling create_build', () => { throw new Error('foo bar'); }); - await expect(buildAction(PLUGIN, noop)).rejects.toThrowErrorMatchingSnapshot(); + await expect(buildTask({ plugin })).rejects.toThrowErrorMatchingSnapshot(); }); }); diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/create_build.test.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_build.test.js similarity index 94% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/create_build.test.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_build.test.js index 42ad1c5ae0cfce..8a4a5a55ce237a 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/create_build.test.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_build.test.js @@ -17,13 +17,14 @@ * under the License. */ -const { resolve } = require('path'); -const { readdirSync, existsSync, unlinkSync } = require('fs'); -const del = require('del'); -const createBuild = require('../create_build'); +import { resolve } from 'path'; +import { readdirSync, existsSync, unlinkSync } from 'fs'; +import del from 'del'; +import { createBuild } from '../create_build'; +import { pluginConfig } from '../../../lib'; const PLUGIN_FIXTURE = resolve(__dirname, '__fixtures__/create_build_test_plugin'); -const PLUGIN = require('../../../lib/plugin_config')(PLUGIN_FIXTURE); +const PLUGIN = pluginConfig(PLUGIN_FIXTURE); const PLUGIN_BUILD_DIR = resolve(PLUGIN_FIXTURE, 'build'); const PLUGIN_BUILD_TARGET = resolve(PLUGIN_BUILD_DIR, 'kibana', PLUGIN.id); diff --git a/packages/kbn-plugin-helpers/tasks/build/integration_tests/create_package.test.js b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_package.test.js similarity index 85% rename from packages/kbn-plugin-helpers/tasks/build/integration_tests/create_package.test.js rename to packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_package.test.js index 9659cfbaa2a304..13de8fa165c291 100644 --- a/packages/kbn-plugin-helpers/tasks/build/integration_tests/create_package.test.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/integration_tests/create_package.test.js @@ -17,14 +17,15 @@ * under the License. */ -const { resolve } = require('path'); -const { statSync } = require('fs'); -const del = require('del'); -const createBuild = require('../create_build'); -const createPackage = require('../create_package'); +import { resolve } from 'path'; +import { statSync } from 'fs'; +import del from 'del'; +import { createBuild } from '../create_build'; +import { createPackage } from '../create_package'; +import { pluginConfig } from '../../../lib'; const PLUGIN_FIXTURE = resolve(__dirname, '__fixtures__/create_package_test_plugin'); -const PLUGIN = require('../../../lib/plugin_config')(PLUGIN_FIXTURE); +const PLUGIN = pluginConfig(PLUGIN_FIXTURE); const PLUGIN_BUILD_DIR = resolve(PLUGIN_FIXTURE, 'build-custom'); const buildVersion = PLUGIN.version; diff --git a/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js b/packages/kbn-plugin-helpers/src/tasks/build/rewrite_package_json.ts similarity index 81% rename from packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js rename to packages/kbn-plugin-helpers/src/tasks/build/rewrite_package_json.ts index 64656baee6fd2b..aaecd11ad82af2 100644 --- a/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js +++ b/packages/kbn-plugin-helpers/src/tasks/build/rewrite_package_json.ts @@ -17,13 +17,18 @@ * under the License. */ -const map = require('through2-map').obj; -const gitInfo = require('./git_info'); +import Through2Map from 'through2-map'; +import File from 'vinyl'; +import { gitInfo } from './git_info'; -module.exports = function rewritePackage(buildSource, buildVersion, kibanaVersion) { - return map(function(file) { +export function rewritePackageJson( + buildSource: string, + buildVersion: string, + kibanaVersion: string +) { + return Through2Map.obj(function (file: File) { if (file.basename === 'package.json' && file.dirname === buildSource) { - const pkg = JSON.parse(file.contents.toString('utf8')); + const pkg = JSON.parse(file.contents!.toString('utf8')); // rewrite the target kibana version while the // file is on it's way to the archive @@ -46,4 +51,4 @@ module.exports = function rewritePackage(buildSource, buildVersion, kibanaVersio return file; }); -}; +} diff --git a/packages/kbn-plugin-helpers/tasks/start/README.md b/packages/kbn-plugin-helpers/src/tasks/start/README.md similarity index 100% rename from packages/kbn-plugin-helpers/tasks/start/README.md rename to packages/kbn-plugin-helpers/src/tasks/start/README.md diff --git a/packages/kbn-plugin-helpers/tasks/start/index.js b/packages/kbn-plugin-helpers/src/tasks/start/index.ts similarity index 94% rename from packages/kbn-plugin-helpers/tasks/start/index.js rename to packages/kbn-plugin-helpers/src/tasks/start/index.ts index b76e91fd5f2898..cf34bdbadf4166 100644 --- a/packages/kbn-plugin-helpers/tasks/start/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/start/index.ts @@ -17,4 +17,4 @@ * under the License. */ -module.exports = require('./start_action'); +export * from './start_task'; diff --git a/packages/kbn-plugin-helpers/tasks/start/start_action.js b/packages/kbn-plugin-helpers/src/tasks/start/start_task.ts similarity index 82% rename from packages/kbn-plugin-helpers/tasks/start/start_action.js rename to packages/kbn-plugin-helpers/src/tasks/start/start_task.ts index 08ef0914311f83..5018fd75981807 100644 --- a/packages/kbn-plugin-helpers/tasks/start/start_action.js +++ b/packages/kbn-plugin-helpers/src/tasks/start/start_task.ts @@ -17,11 +17,15 @@ * under the License. */ -const execFileSync = require('child_process').execFileSync; -const { join } = require('path'); -const split = require('argv-split'); +import { execFileSync } from 'child_process'; +import { join } from 'path'; -module.exports = function(plugin, run, options) { +// @ts-ignore +import split from 'argv-split'; + +import { TaskContext } from '../../lib'; + +export function startTask({ plugin, options }: TaskContext) { options = options || {}; const cmd = 'node'; @@ -31,7 +35,7 @@ module.exports = function(plugin, run, options) { let args = nodeOptions.concat([script, '--dev', '--plugin-path', plugin.root]); if (Array.isArray(plugin.includePlugins)) { - plugin.includePlugins.forEach(path => { + plugin.includePlugins.forEach((path) => { args = args.concat(['--plugin-path', path]); }); } @@ -44,4 +48,4 @@ module.exports = function(plugin, run, options) { cwd: plugin.kibanaRoot, stdio: ['ignore', 1, 2], }); -}; +} diff --git a/packages/kbn-plugin-helpers/tasks/test/all/README.md b/packages/kbn-plugin-helpers/src/tasks/test/all/README.md similarity index 100% rename from packages/kbn-plugin-helpers/tasks/test/all/README.md rename to packages/kbn-plugin-helpers/src/tasks/test/all/README.md diff --git a/packages/kbn-plugin-helpers/tasks/build/index.js b/packages/kbn-plugin-helpers/src/tasks/test/all/index.ts similarity index 94% rename from packages/kbn-plugin-helpers/tasks/build/index.js rename to packages/kbn-plugin-helpers/src/tasks/test/all/index.ts index b01a64c7f9be24..be8db50825fc96 100644 --- a/packages/kbn-plugin-helpers/tasks/build/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/test/all/index.ts @@ -17,4 +17,4 @@ * under the License. */ -module.exports = require('./build_action'); +export * from './test_all_task'; diff --git a/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js b/packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts similarity index 89% rename from packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js rename to packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts index f16e391b2b2113..d07c19291d2cbd 100644 --- a/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js +++ b/packages/kbn-plugin-helpers/src/tasks/test/all/test_all_task.ts @@ -17,7 +17,9 @@ * under the License. */ -module.exports = function testAllAction(plugin, run) { +import { TaskContext } from '../../../lib'; + +export function testAllTask({ run }: TaskContext) { run('testMocha'); run('testKarma'); -}; +} diff --git a/packages/kbn-plugin-helpers/tasks/test/karma/README.md b/packages/kbn-plugin-helpers/src/tasks/test/karma/README.md similarity index 100% rename from packages/kbn-plugin-helpers/tasks/test/karma/README.md rename to packages/kbn-plugin-helpers/src/tasks/test/karma/README.md diff --git a/packages/kbn-plugin-helpers/tasks/test/all/index.js b/packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts similarity index 94% rename from packages/kbn-plugin-helpers/tasks/test/all/index.js rename to packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts index 0cdc615ee867fd..3089357b499910 100644 --- a/packages/kbn-plugin-helpers/tasks/test/all/index.js +++ b/packages/kbn-plugin-helpers/src/tasks/test/karma/index.ts @@ -17,4 +17,4 @@ * under the License. */ -module.exports = require('./test_all_action'); +export * from './test_karma_task'; diff --git a/packages/kbn-plugin-helpers/tasks/test/karma/test_karma_action.js b/packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts similarity index 86% rename from packages/kbn-plugin-helpers/tasks/test/karma/test_karma_action.js rename to packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts index e1ba8caee7f9a1..2fe8134209894f 100644 --- a/packages/kbn-plugin-helpers/tasks/test/karma/test_karma_action.js +++ b/packages/kbn-plugin-helpers/src/tasks/test/karma/test_karma_task.ts @@ -17,10 +17,12 @@ * under the License. */ -const execFileSync = require('child_process').execFileSync; -const winCmd = require('../../../lib/win_cmd'); +import { execFileSync } from 'child_process'; -module.exports = function testKarmaAction(plugin, run, options) { +import { TaskContext } from '../../../lib'; +import { winCmd } from '../../../lib/win_cmd'; + +export function testKarmaTask({ plugin, options }: TaskContext) { options = options || {}; const kbnServerArgs = ['--kbnServer.plugin-path=' + plugin.root]; @@ -37,4 +39,4 @@ module.exports = function testKarmaAction(plugin, run, options) { cwd: plugin.kibanaRoot, stdio: ['ignore', 1, 2], }); -}; +} diff --git a/packages/kbn-plugin-helpers/tasks/test/mocha/README.md b/packages/kbn-plugin-helpers/src/tasks/test/mocha/README.md similarity index 100% rename from packages/kbn-plugin-helpers/tasks/test/mocha/README.md rename to packages/kbn-plugin-helpers/src/tasks/test/mocha/README.md diff --git a/packages/kbn-plugin-helpers/src/tasks/test/mocha/index.ts b/packages/kbn-plugin-helpers/src/tasks/test/mocha/index.ts new file mode 100644 index 00000000000000..74e53062d4f01a --- /dev/null +++ b/packages/kbn-plugin-helpers/src/tasks/test/mocha/index.ts @@ -0,0 +1,20 @@ +/* + * 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 * from './test_mocha_task'; diff --git a/packages/kbn-plugin-helpers/tasks/test/mocha/test_mocha_action.js b/packages/kbn-plugin-helpers/src/tasks/test/mocha/test_mocha_task.ts similarity index 86% rename from packages/kbn-plugin-helpers/tasks/test/mocha/test_mocha_action.js rename to packages/kbn-plugin-helpers/src/tasks/test/mocha/test_mocha_task.ts index 7cc9864baa9756..a79ef0a59d19a9 100644 --- a/packages/kbn-plugin-helpers/tasks/test/mocha/test_mocha_action.js +++ b/packages/kbn-plugin-helpers/src/tasks/test/mocha/test_mocha_task.ts @@ -17,10 +17,12 @@ * under the License. */ -const execFileSync = require('child_process').execFileSync; -const globby = require('globby'); +import { execFileSync } from 'child_process'; +import globby from 'globby'; -module.exports = function(plugin, run, options) { +import { TaskContext } from '../../../lib'; + +export function testMochaTask({ plugin, options }: TaskContext) { options = options || {}; let testPatterns = plugin.serverTestPatterns; @@ -43,4 +45,4 @@ module.exports = function(plugin, run, options) { stdio: ['ignore', 1, 2], } ); -}; +} diff --git a/packages/kbn-plugin-helpers/tasks/build/create_build.js b/packages/kbn-plugin-helpers/tasks/build/create_build.js deleted file mode 100644 index 7d42dc13ef278d..00000000000000 --- a/packages/kbn-plugin-helpers/tasks/build/create_build.js +++ /dev/null @@ -1,205 +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. - */ - -const path = require('path'); -const relative = require('path').relative; -const { readFileSync, writeFileSync, unlinkSync, existsSync } = require('fs'); -const execa = require('execa'); -const sass = require('node-sass'); -const del = require('del'); -const vfs = require('vinyl-fs'); -const rename = require('gulp-rename'); -const through = require('through2'); -const minimatch = require('minimatch'); -const gulpBabel = require('gulp-babel'); -const { promisify } = require('util'); -const { pipeline } = require('stream'); - -const rewritePackageJson = require('./rewrite_package_json'); -const winCmd = require('../../lib/win_cmd'); - -const asyncPipeline = promisify(pipeline); - -// `link:` dependencies create symlinks, but we don't want to include symlinks -// in the built zip file. Therefore we remove all symlinked dependencies, so we -// can re-create them when installing the plugin. -function removeSymlinkDependencies(root) { - const nodeModulesPattern = path.join(root, '**', 'node_modules', '**'); - - return through.obj((file, enc, cb) => { - const isSymlink = file.symlink != null; - const isDependency = minimatch(file.path, nodeModulesPattern); - - if (isSymlink && isDependency) { - unlinkSync(file.path); - } - - cb(); - }); -} - -// parse a ts config file -function parseTsconfig(pluginSourcePath, configPath) { - const ts = require(path.join(pluginSourcePath, 'node_modules', 'typescript')); // eslint-disable-line import/no-dynamic-require - - const { error, config } = ts.parseConfigFileTextToJson( - configPath, - readFileSync(configPath, 'utf8') - ); - - if (error) { - throw error; - } - - return config; -} - -// transpile with babel -async function transpileWithBabel(srcGlobs, buildRoot, presets) { - await asyncPipeline( - vfs.src( - srcGlobs.concat([ - '!**/*.d.ts', - '!**/*.{test,test.mocks,mock,mocks}.{ts,tsx}', - '!**/node_modules/**', - '!**/bower_components/**', - '!**/__tests__/**', - ]), - { - cwd: buildRoot, - } - ), - - gulpBabel({ - babelrc: false, - presets, - }), - - vfs.dest(buildRoot) - ); -} - -module.exports = function createBuild(plugin, buildTarget, buildVersion, kibanaVersion, files) { - const buildSource = plugin.root; - const buildRoot = path.join(buildTarget, 'kibana', plugin.id); - - return del(buildTarget) - .then(function() { - return new Promise(function(resolve, reject) { - vfs - .src(files, { - cwd: buildSource, - base: buildSource, - allowEmpty: true, - }) - // modify the package.json file - .pipe(rewritePackageJson(buildSource, buildVersion, kibanaVersion)) - - // put all files inside the correct directories - .pipe( - rename(function nestFileInDir(filePath) { - const nonRelativeDirname = filePath.dirname.replace(/^(\.\.\/?)+/g, ''); - filePath.dirname = path.join(relative(buildTarget, buildRoot), nonRelativeDirname); - }) - ) - - .pipe(vfs.dest(buildTarget)) - .on('end', resolve) - .on('error', reject); - }); - }) - .then(function() { - if (plugin.skipInstallDependencies) { - return; - } - - // install packages in build - execa.sync(winCmd('yarn'), ['install', '--production', '--pure-lockfile'], { - cwd: buildRoot, - }); - }) - .then(function() { - if (!plugin.styleSheetToCompile) { - return; - } - - const file = path.resolve(plugin.root, plugin.styleSheetToCompile); - if (!existsSync(file)) { - throw new Error(`Path provided for styleSheetToCompile does not exist: ${file}`); - } - - const outputFileName = path.basename(file, path.extname(file)) + '.css'; - const output = path.join(buildRoot, path.dirname(plugin.styleSheetToCompile), outputFileName); - - const rendered = sass.renderSync({ file, output }); - writeFileSync(output, rendered.css); - - del.sync([path.join(buildRoot, '**', '*.s{a,c}ss')]); - }) - .then(async function() { - const buildConfigPath = path.join(buildRoot, 'tsconfig.json'); - - if (!existsSync(buildConfigPath)) { - return; - } - - // attempt to patch the extends path in the tsconfig file - const buildConfig = parseTsconfig(buildSource, buildConfigPath); - - if (buildConfig.extends) { - buildConfig.extends = path.join(relative(buildRoot, buildSource), buildConfig.extends); - - writeFileSync(buildConfigPath, JSON.stringify(buildConfig)); - } - - // Transpile ts server code - // - // Include everything except content from public folders - await transpileWithBabel(['**/*.{ts,tsx}', '!**/public/**'], buildRoot, [ - require.resolve('@kbn/babel-preset/node_preset'), - ]); - - // Transpile ts client code - // - // Include everything inside a public directory - await transpileWithBabel(['**/public/**/*.{ts,tsx}'], buildRoot, [ - require.resolve('@kbn/babel-preset/webpack_preset'), - ]); - - del.sync([ - path.join(buildRoot, '**', '*.{ts,tsx,d.ts}'), - path.join(buildRoot, 'tsconfig.json'), - ]); - }) - .then(function() { - const buildFiles = [relative(buildTarget, buildRoot) + '/**/*']; - - return new Promise((resolve, reject) => { - vfs - .src(buildFiles, { - cwd: buildTarget, - base: buildTarget, - resolveSymlinks: false, - }) - .pipe(removeSymlinkDependencies(buildRoot)) - .on('finish', resolve) - .on('error', reject); - }); - }); -}; diff --git a/packages/kbn-plugin-helpers/tasks/test/mocha/index.js b/packages/kbn-plugin-helpers/tasks/test/mocha/index.js deleted file mode 100644 index 1ab022db588f92..00000000000000 --- a/packages/kbn-plugin-helpers/tasks/test/mocha/index.js +++ /dev/null @@ -1,20 +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 = require('./test_mocha_action'); diff --git a/packages/kbn-plugin-helpers/tsconfig.json b/packages/kbn-plugin-helpers/tsconfig.json index f5559aa7290c5d..d0dbe1e44f0fa5 100644 --- a/packages/kbn-plugin-helpers/tsconfig.json +++ b/packages/kbn-plugin-helpers/tsconfig.json @@ -1,4 +1,11 @@ { "extends": "../../tsconfig.json", - "include": ["lib/index.d.ts"] + "compilerOptions": { + "outDir": "target", + "declaration": true, + "sourceMap": true + }, + "include": [ + "src/**/*.ts" + ] } diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 1b670eb8cd8169..baaac3d8d4a865 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -4859,7 +4859,7 @@ class ProcRunner { this.closing = false; this.procs = []; this.signalUnsubscribe = exit_hook_1.default(() => { - this.teardown().catch(error => { + this.teardown().catch((error) => { log.error(`ProcRunner teardown error: ${error.stack}`); }); }); @@ -4898,7 +4898,7 @@ class ProcRunner { try { if (wait instanceof RegExp) { // wait for process to log matching line - await Rx.race(proc.lines$.pipe(operators_1.filter(line => wait.test(line)), operators_1.first(), operators_1.catchError(err => { + await Rx.race(proc.lines$.pipe(operators_1.filter((line) => wait.test(line)), operators_1.first(), operators_1.catchError((err) => { if (err.name !== 'EmptyError') { throw errors_1.createCliError(`[${name}] exited without matching pattern: ${wait}`); } @@ -4943,7 +4943,7 @@ class ProcRunner { * @return {Promise} */ async waitForAllToStop() { - await Promise.all(this.procs.map(proc => proc.outcomePromise)); + await Promise.all(this.procs.map((proc) => proc.outcomePromise)); } /** * Close the ProcRunner and stop all running @@ -4959,14 +4959,14 @@ class ProcRunner { this.closing = true; this.signalUnsubscribe(); if (!signal && this.procs.length > 0) { - this.log.warning('%d processes left running, stop them with procs.stop(name):', this.procs.length, this.procs.map(proc => proc.name)); + this.log.warning('%d processes left running, stop them with procs.stop(name):', this.procs.length, this.procs.map((proc) => proc.name)); } await Promise.all(this.procs.map(async (proc) => { await proc.stop(signal === 'exit' ? 'SIGKILL' : signal); })); } getProc(name) { - return this.procs.find(proc => { + return this.procs.find((proc) => { return proc.name === name; }); } @@ -4979,14 +4979,14 @@ class ProcRunner { }; // tie into proc outcome$, remove from _procs on compete proc.outcome$.subscribe({ - next: code => { + next: (code) => { const duration = moment_1.default.duration(Date.now() - startMs); this.log.info('[%s] exited with %s after %s', name, code, duration.humanize()); }, complete: () => { remove(); }, - error: error => { + error: (error) => { if (this.closing) { this.log.error(error); } @@ -33599,8 +33599,8 @@ function startProc(name, options, log) { return code; })), // observe first error event - Rx.fromEvent(childProcess, 'error').pipe(operators_1.take(1), operators_1.mergeMap(err => Rx.throwError(err)))).pipe(operators_1.share()); - const lines$ = Rx.merge(observe_lines_1.observeLines(childProcess.stdout), observe_lines_1.observeLines(childProcess.stderr)).pipe(operators_1.tap(line => log.write(` ${chalk_1.default.gray('proc')} [${chalk_1.default.gray(name)}] ${line}`)), operators_1.share()); + Rx.fromEvent(childProcess, 'error').pipe(operators_1.take(1), operators_1.mergeMap((err) => Rx.throwError(err)))).pipe(operators_1.share()); + const lines$ = Rx.merge(observe_lines_1.observeLines(childProcess.stdout), observe_lines_1.observeLines(childProcess.stderr)).pipe(operators_1.tap((line) => log.write(` ${chalk_1.default.gray('proc')} [${chalk_1.default.gray(name)}] ${line}`)), operators_1.share()); const outcomePromise = Rx.merge(lines$.pipe(operators_1.ignoreElements()), outcome$).toPromise(); async function stop(signal) { if (stopCalled) { @@ -36584,7 +36584,7 @@ const operators_1 = __webpack_require__(270); * - fails on the first "error" event */ function observeReadable(readable) { - return Rx.race(Rx.fromEvent(readable, 'end').pipe(operators_1.first(), operators_1.ignoreElements()), Rx.fromEvent(readable, 'error').pipe(operators_1.first(), operators_1.mergeMap(err => Rx.throwError(err)))); + return Rx.race(Rx.fromEvent(readable, 'end').pipe(operators_1.first(), operators_1.ignoreElements()), Rx.fromEvent(readable, 'error').pipe(operators_1.first(), operators_1.mergeMap((err) => Rx.throwError(err)))); } exports.observeReadable = observeReadable; @@ -36894,7 +36894,7 @@ class ToolingLogCollectingWriter extends tooling_log_text_writer_1.ToolingLogTex super({ level: 'verbose', writeTo: { - write: msg => { + write: (msg) => { // trim trailing new line this.messages.push(msg.slice(0, -1)); }, @@ -39475,7 +39475,7 @@ async function run(fn, options = {}) { level: tooling_log_1.pickLevelFromFlags(flags), writeTo: process.stdout, }); - process.on('unhandledRejection', error => { + process.on('unhandledRejection', (error) => { log.error('UNHANDLED PROMISE REJECTION'); log.error(error instanceof Error ? error @@ -39589,7 +39589,7 @@ function combineErrors(errors) { const exitCode = errors .filter(isFailError) .reduce((acc, error) => Math.max(acc, error.exitCode), 1); - const showHelp = errors.some(error => isFailError(error) && error.showHelp); + const showHelp = errors.some((error) => isFailError(error) && error.showHelp); const message = errors.reduce((acc, error) => { if (isFailError(error)) { return acc + '\n' + error.message; @@ -40091,7 +40091,7 @@ exports.uriencode = (strings, ...values) => { return queue.reduce((acc, string, i) => `${acc}${encodeURIComponent(values[i])}${string}`, leadingString); }; const DEFAULT_MAX_ATTEMPTS = 5; -const delay = (ms) => new Promise(resolve => { +const delay = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); }); class KbnClientRequester { @@ -43984,7 +43984,7 @@ class CiStatsReporter { const reason = ((_d = (_c = error) === null || _c === void 0 ? void 0 : _c.response) === null || _d === void 0 ? void 0 : _d.status) ? `${error.response.status} response` : 'no response'; this.log.warning(`failed to reach kibana-ci-stats service [reason=${reason}], retrying in ${attempt} seconds`); - await new Promise(resolve => setTimeout(resolve, attempt * 1000)); + await new Promise((resolve) => setTimeout(resolve, attempt * 1000)); } } } diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index be56fad8aa0ce1..234877e9ae6268 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -54,7 +54,7 @@ "multimatch": "^4.0.0", "ncp": "^2.0.0", "ora": "^1.4.0", - "prettier": "^1.19.1", + "prettier": "^2.0.5", "read-pkg": "^5.2.0", "rxjs": "^6.5.3", "spawn-sync": "^1.0.15", diff --git a/packages/kbn-pm/src/cli.ts b/packages/kbn-pm/src/cli.ts index c2f49356957f7f..94f348e1835ed9 100644 --- a/packages/kbn-pm/src/cli.ts +++ b/packages/kbn-pm/src/cli.ts @@ -28,8 +28,8 @@ import { log } from './utils/log'; function help() { const availableCommands = Object.keys(commands) - .map(commandName => commands[commandName]) - .map(command => `${command.name} - ${command.description}`); + .map((commandName) => commands[commandName]) + .map((command) => `${command.name} - ${command.description}`); log.write(dedent` usage: kbn [] diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index d0aa220f25f661..6146aeab21db45 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -69,7 +69,7 @@ export const BootstrapCommand: ICommand = { log.write(chalk.bold('\nLinking executables completed, running `kbn:bootstrap` scripts\n')); const checksums = options.cache ? await getAllChecksums(kbn, log) : false; - await parallelizeBatches(batchedProjects, async project => { + await parallelizeBatches(batchedProjects, async (project) => { if (project.hasScript('kbn:bootstrap')) { const cacheFile = new BootstrapCacheFile(kbn, project, checksums); if (cacheFile.isValid()) { diff --git a/packages/kbn-pm/src/commands/run.ts b/packages/kbn-pm/src/commands/run.ts index 2f4d9e8453d093..989bfef19c3809 100644 --- a/packages/kbn-pm/src/commands/run.ts +++ b/packages/kbn-pm/src/commands/run.ts @@ -43,7 +43,7 @@ export const RunCommand: ICommand = { chalk.bold(`\nRunning script [${chalk.green(scriptName)}] in batched topological order\n`) ); - await parallelizeBatches(batchedProjects, async pkg => { + await parallelizeBatches(batchedProjects, async (pkg) => { if (pkg.hasScript(scriptName)) { await pkg.runScriptStreaming(scriptName, scriptArgs); } diff --git a/packages/kbn-pm/src/commands/watch.ts b/packages/kbn-pm/src/commands/watch.ts index b5c493372b04f7..2e18b02a1c860c 100644 --- a/packages/kbn-pm/src/commands/watch.ts +++ b/packages/kbn-pm/src/commands/watch.ts @@ -83,7 +83,7 @@ export const WatchCommand: ICommand = { batchedProjects.push([projects.get(kibanaProjectName)!]); } - await parallelizeBatches(batchedProjects, async pkg => { + await parallelizeBatches(batchedProjects, async (pkg) => { const completionHint = await waitUntilWatchIsReady( pkg.runScriptStreaming(watchScriptName).stdout ); diff --git a/packages/kbn-pm/src/production/build_production_projects.ts b/packages/kbn-pm/src/production/build_production_projects.ts index 0d4be8b0160770..689bf51cd7bdfb 100644 --- a/packages/kbn-pm/src/production/build_production_projects.ts +++ b/packages/kbn-pm/src/production/build_production_projects.ts @@ -46,7 +46,7 @@ export async function buildProductionProjects({ const projectGraph = buildProjectGraph(projects); const batchedProjects = topologicallyBatchProjects(projects, projectGraph); - const projectNames = [...projects.values()].map(project => project.name); + const projectNames = [...projects.values()].map((project) => project.name); log.write(`Preparing production build for [${projectNames.join(', ')}]`); for (const batch of batchedProjects) { @@ -82,7 +82,7 @@ async function getProductionProjects(rootPath: string, onlyOSS?: boolean) { productionProjects.delete('kibana'); if (onlyOSS) { - productionProjects.forEach(project => { + productionProjects.forEach((project) => { if (project.getBuildConfig().oss === false) { productionProjects.delete(project.json.name); } diff --git a/packages/kbn-pm/src/run.ts b/packages/kbn-pm/src/run.ts index 44bf5a91ee1b19..c3879c701d785b 100644 --- a/packages/kbn-pm/src/run.ts +++ b/packages/kbn-pm/src/run.ts @@ -71,7 +71,7 @@ export async function runCommand(command: ICommand, config: Omit 0) { - const metaOutput = keys.map(key => { + const metaOutput = keys.map((key) => { const value = e.meta[key]; return `${key}: ${value}`; }); diff --git a/packages/kbn-pm/src/utils/bootstrap_cache_file.ts b/packages/kbn-pm/src/utils/bootstrap_cache_file.ts index 7d87179f34605b..282483e10ccf2d 100644 --- a/packages/kbn-pm/src/utils/bootstrap_cache_file.ts +++ b/packages/kbn-pm/src/utils/bootstrap_cache_file.ts @@ -39,7 +39,7 @@ export class BootstrapCacheFile { // sort deps by name so that the key is stable .sort((a, b) => a.name.localeCompare(b.name)) // get the cacheKey for each project, return undefined if the cache key couldn't be determined - .map(p => { + .map((p) => { const cacheKey = checksums.get(p.name); if (cacheKey) { return `${p.name}:${cacheKey}`; @@ -47,7 +47,7 @@ export class BootstrapCacheFile { }); // if any of the relevant cache keys are undefined then the projectCacheKey must be too - this.expectedValue = projectAndDepCacheKeys.some(k => !k) + this.expectedValue = projectAndDepCacheKeys.some((k) => !k) ? undefined : [ `# this is only human readable for debugging, please don't try to parse this`, diff --git a/packages/kbn-pm/src/utils/fs.ts b/packages/kbn-pm/src/utils/fs.ts index 9484c3a61e6082..44fc59bdeba966 100644 --- a/packages/kbn-pm/src/utils/fs.ts +++ b/packages/kbn-pm/src/utils/fs.ts @@ -49,7 +49,7 @@ async function statTest(path: string, block: (stats: fs.Stats) => boolean) { * @param path */ export async function isSymlink(path: string) { - return await statTest(path, stats => stats.isSymbolicLink()); + return await statTest(path, (stats) => stats.isSymbolicLink()); } /** @@ -57,7 +57,7 @@ export async function isSymlink(path: string) { * @param path */ export async function isDirectory(path: string) { - return await statTest(path, stats => stats.isDirectory()); + return await statTest(path, (stats) => stats.isDirectory()); } /** @@ -65,7 +65,7 @@ export async function isDirectory(path: string) { * @param path */ export async function isFile(path: string) { - return await statTest(path, stats => stats.isFile()); + return await statTest(path, (stats) => stats.isFile()); } /** diff --git a/packages/kbn-pm/src/utils/kibana.ts b/packages/kbn-pm/src/utils/kibana.ts index 58af98b2a92dbd..7fca4bd01822bc 100644 --- a/packages/kbn-pm/src/utils/kibana.ts +++ b/packages/kbn-pm/src/utils/kibana.ts @@ -103,11 +103,11 @@ export class Kibana { const allProjects = this.getAllProjects(); const filteredProjects: ProjectMap = new Map(); - const pkgJsonPaths = Array.from(allProjects.values()).map(p => p.packageJsonLocation); + const pkgJsonPaths = Array.from(allProjects.values()).map((p) => p.packageJsonLocation); const filteredPkgJsonGlobs = getProjectPaths({ ...options, rootPath: this.kibanaProject.path, - }).map(g => Path.resolve(g, 'package.json')); + }).map((g) => Path.resolve(g, 'package.json')); const matchingPkgJsonPaths = multimatch(pkgJsonPaths, filteredPkgJsonGlobs); for (const project of allProjects.values()) { diff --git a/packages/kbn-pm/src/utils/link_project_executables.test.ts b/packages/kbn-pm/src/utils/link_project_executables.test.ts index a6334ec850860e..a19e1fd66f334c 100644 --- a/packages/kbn-pm/src/utils/link_project_executables.test.ts +++ b/packages/kbn-pm/src/utils/link_project_executables.test.ts @@ -70,7 +70,7 @@ const projectGraph = buildProjectGraph(projectsByName); function getFsMockCalls() { const fs = require('./fs'); const fsMockCalls: { [key: string]: any[][] } = {}; - Object.keys(fs).map(key => { + Object.keys(fs).map((key) => { if (jest.isMockFunction(fs[key])) { fsMockCalls[key] = fs[key].mock.calls; } diff --git a/packages/kbn-pm/src/utils/link_project_executables.ts b/packages/kbn-pm/src/utils/link_project_executables.ts index 25fb11f17f7823..b403dfb2ecf2e2 100644 --- a/packages/kbn-pm/src/utils/link_project_executables.ts +++ b/packages/kbn-pm/src/utils/link_project_executables.ts @@ -55,9 +55,7 @@ export async function linkProjectExecutables( const dest = resolve(binsDir, name); // Get relative project path with normalized path separators. - const projectRelativePath = relative(project.path, srcPath) - .split(sep) - .join('/'); + const projectRelativePath = relative(project.path, srcPath).split(sep).join('/'); log.write(chalk`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}`); diff --git a/packages/kbn-pm/src/utils/parallelize.test.ts b/packages/kbn-pm/src/utils/parallelize.test.ts index fa23ecbb8c1e78..e85b40e0c67d84 100644 --- a/packages/kbn-pm/src/utils/parallelize.test.ts +++ b/packages/kbn-pm/src/utils/parallelize.test.ts @@ -22,7 +22,7 @@ import { parallelizeBatches } from './parallelize'; // As promises resolve async, we use this helper to wait for all promises that // have been resolved to complete (aka call `then`). const tick = () => - new Promise(resolve => { + new Promise((resolve) => { setTimeout(resolve, 0); }); @@ -32,7 +32,7 @@ test('parallelizes batches', async () => { const baz = createPromiseWithResolve(); const batches = [[foo, bar], [baz]]; - const parallelize = parallelizeBatches(batches, async obj => { + const parallelize = parallelizeBatches(batches, async (obj) => { obj.called = true; await obj.promise; }); @@ -82,7 +82,7 @@ test('schedules at most 4 calls at the same time (concurrency)', async () => { const foobar = createPromiseWithResolve(); const batches = [[foo, bar, baz, quux, foobar]]; - const parallelize = parallelizeBatches(batches, async obj => { + const parallelize = parallelizeBatches(batches, async (obj) => { obj.called = true; await obj.promise; }); @@ -113,7 +113,7 @@ test('rejects if any promise rejects', async () => { const baz = createPromiseWithResolve(); const batches = [[foo, bar], [baz]]; - const parallelize = parallelizeBatches(batches, async obj => { + const parallelize = parallelizeBatches(batches, async (obj) => { await obj.promise; }); diff --git a/packages/kbn-pm/src/utils/project.ts b/packages/kbn-pm/src/utils/project.ts index 7b0bbed5c3f46f..91a3a5365b60ed 100644 --- a/packages/kbn-pm/src/utils/project.ts +++ b/packages/kbn-pm/src/utils/project.ts @@ -229,10 +229,10 @@ export class Project { // check for any cross-project dependency for (const name of Object.keys(workspacesInfo)) { const workspace = workspacesInfo[name]; - workspace.workspaceDependencies.forEach(w => unusedWorkspaces.delete(w)); + workspace.workspaceDependencies.forEach((w) => unusedWorkspaces.delete(w)); } - unusedWorkspaces.forEach(name => { + unusedWorkspaces.forEach((name) => { const { dependencies, devDependencies } = this.json; const nodeModulesPath = Path.resolve(this.nodeModulesLocation, name); const isDependency = dependencies && dependencies.hasOwnProperty(name); diff --git a/packages/kbn-pm/src/utils/project_checksums.ts b/packages/kbn-pm/src/utils/project_checksums.ts index 7d939e715d411c..46dde1b32c1587 100644 --- a/packages/kbn-pm/src/utils/project_checksums.ts +++ b/packages/kbn-pm/src/utils/project_checksums.ts @@ -49,8 +49,8 @@ async function getChangesForProjects(projects: ProjectMap, kbn: Kibana, log: Too '--exclude-standard', '--', ...Array.from(projects.values()) - .filter(p => kbn.isPartOfRepo(p)) - .map(p => p.path), + .filter((p) => kbn.isPartOfRepo(p)) + .map((p) => p.path), ], { cwd: kbn.getAbsolute(), @@ -265,7 +265,7 @@ export async function getAllChecksums(kbn: Kibana, log: ToolingLog) { const cacheKeys: ChecksumMap = new Map(); await Promise.all( - Array.from(projects.values()).map(async project => { + Array.from(projects.values()).map(async (project) => { cacheKeys.set( project.name, await getChecksum(project, changesByProject.get(project), yarnLock, kbn, log) diff --git a/packages/kbn-pm/src/utils/projects.test.ts b/packages/kbn-pm/src/utils/projects.test.ts index ba093b9d5eba1a..068c72286872a9 100644 --- a/packages/kbn-pm/src/utils/projects.test.ts +++ b/packages/kbn-pm/src/utils/projects.test.ts @@ -208,7 +208,7 @@ describe('#topologicallyBatchProjects', () => { test('batches projects topologically based on their project dependencies', async () => { const batches = topologicallyBatchProjects(projects, graph); - const expectedBatches = batches.map(batch => batch.map(project => project.name)); + const expectedBatches = batches.map((batch) => batch.map((project) => project.name)); expect(expectedBatches).toMatchSnapshot(); }); @@ -219,7 +219,7 @@ describe('#topologicallyBatchProjects', () => { const batches = topologicallyBatchProjects(projects, graph); - const expectedBatches = batches.map(batch => batch.map(project => project.name)); + const expectedBatches = batches.map((batch) => batch.map((project) => project.name)); expect(expectedBatches).toMatchSnapshot(); }); @@ -228,7 +228,7 @@ describe('#topologicallyBatchProjects', () => { test('batches projects topologically based on their project dependencies and workspaces', async () => { const batches = topologicallyBatchProjects(projects, graph, { batchByWorkspace: true }); - const expectedBatches = batches.map(batch => batch.map(project => project.name)); + const expectedBatches = batches.map((batch) => batch.map((project) => project.name)); expect(expectedBatches).toEqual([['kibana'], ['bar', 'foo'], ['baz', 'zorge'], ['quux']]); }); diff --git a/packages/kbn-pm/src/utils/projects.ts b/packages/kbn-pm/src/utils/projects.ts index a6f174b1fc5a1b..1c3bf0fa3091a4 100644 --- a/packages/kbn-pm/src/utils/projects.ts +++ b/packages/kbn-pm/src/utils/projects.ts @@ -137,7 +137,9 @@ export function topologicallyBatchProjects( const batches = []; if (batchByWorkspace) { - const workspaceRootProject = Array.from(projectsToBatch.values()).find(p => p.isWorkspaceRoot); + const workspaceRootProject = Array.from(projectsToBatch.values()).find( + (p) => p.isWorkspaceRoot + ); if (!workspaceRootProject) { throw new CliError(`There was no yarn workspace root found.`); @@ -167,7 +169,7 @@ export function topologicallyBatchProjects( const batch = []; for (const projectName of projectsLeftToBatch) { const projectDeps = projectGraph.get(projectName)!; - const needsDependenciesBatched = projectDeps.some(dep => projectsLeftToBatch.has(dep.name)); + const needsDependenciesBatched = projectDeps.some((dep) => projectsLeftToBatch.has(dep.name)); if (!needsDependenciesBatched) { batch.push(projectsToBatch.get(projectName)!); @@ -188,7 +190,7 @@ export function topologicallyBatchProjects( batches.push(batch); - batch.forEach(project => projectsLeftToBatch.delete(project.name)); + batch.forEach((project) => projectsLeftToBatch.delete(project.name)); } return batches; @@ -211,7 +213,7 @@ export function includeTransitiveProjects( ? project.productionDependencies : project.allDependencies; - Object.keys(dependencies).forEach(dep => { + Object.keys(dependencies).forEach((dep) => { if (allProjects.has(dep)) { toProcess.push(allProjects.get(dep)!); } diff --git a/packages/kbn-pm/src/utils/watch.ts b/packages/kbn-pm/src/utils/watch.ts index 0ec8b50d83905b..1998c5199fb735 100644 --- a/packages/kbn-pm/src/utils/watch.ts +++ b/packages/kbn-pm/src/utils/watch.ts @@ -56,20 +56,20 @@ function getWatchHandlers( }: IWatchOptions ) { const typescriptHandler = buildOutput$.pipe( - first(data => data.includes('$ tsc')), + first((data) => data.includes('$ tsc')), map(() => buildOutput$.pipe( - first(data => data.includes('Compilation complete.')), + first((data) => data.includes('Compilation complete.')), mapTo('tsc') ) ) ); const webpackHandler = buildOutput$.pipe( - first(data => data.includes('$ webpack')), + first((data) => data.includes('$ webpack')), map(() => buildOutput$.pipe( - first(data => data.includes('Chunk Names')), + first((data) => data.includes('Chunk Names')), mapTo('webpack') ) ) @@ -100,7 +100,7 @@ export function waitUntilWatchIsReady(stream: NodeJS.EventEmitter, opts: IWatchO return Rx.race(getWatchHandlers(buildOutput$, opts)) .pipe( - mergeMap(whenReady => whenReady), + mergeMap((whenReady) => whenReady), finalize(() => { stream.removeListener('data', onDataListener); stream.removeListener('end', onEndListener); diff --git a/packages/kbn-pm/src/utils/workspaces.ts b/packages/kbn-pm/src/utils/workspaces.ts index 22fa8636aea906..830a713e84ad47 100644 --- a/packages/kbn-pm/src/utils/workspaces.ts +++ b/packages/kbn-pm/src/utils/workspaces.ts @@ -48,7 +48,7 @@ export async function workspacePackagePaths(rootPath: string): Promise for (const pattern of workspacesPathsPatterns) { if (pattern.startsWith('!')) { const pathToRemove = path.join(rootPath, pattern.slice(1), 'package.json'); - workspaceProjectsPaths = workspaceProjectsPaths.filter(p => p !== pathToRemove); + workspaceProjectsPaths = workspaceProjectsPaths.filter((p) => p !== pathToRemove); } } diff --git a/packages/kbn-spec-to-console/bin/spec_to_console.js b/packages/kbn-spec-to-console/bin/spec_to_console.js index 20b42c67f3b898..432890a9cb903e 100644 --- a/packages/kbn-spec-to-console/bin/spec_to_console.js +++ b/packages/kbn-spec-to-console/bin/spec_to_console.js @@ -46,7 +46,7 @@ console.log(); console.log(files); console.log(); -files.forEach(file => { +files.forEach((file) => { const spec = JSON.parse(fs.readFileSync(file)); const convertedSpec = convert(spec); if (!Object.keys(convertedSpec).length) { diff --git a/packages/kbn-spec-to-console/lib/convert.js b/packages/kbn-spec-to-console/lib/convert.js index 9648ef0b85a4fc..bd0dbb429cff37 100644 --- a/packages/kbn-spec-to-console/lib/convert.js +++ b/packages/kbn-spec-to-console/lib/convert.js @@ -22,7 +22,7 @@ const convertMethods = require('./convert/methods'); const convertPaths = require('./convert/paths'); const convertParts = require('./convert/parts'); -module.exports = spec => { +module.exports = (spec) => { const result = {}; /** * TODO: @@ -34,7 +34,7 @@ module.exports = spec => { * from being used in autocompletion. It would be really nice if we could use this information * instead of just not including it. */ - Object.keys(spec).forEach(api => { + Object.keys(spec).forEach((api) => { const source = spec[api]; if (!source.url) { @@ -42,7 +42,7 @@ module.exports = spec => { } if (source.url.path) { - if (source.url.paths.every(path => Boolean(path.deprecated))) { + if (source.url.paths.every((path) => Boolean(path.deprecated))) { return; } } @@ -61,10 +61,10 @@ module.exports = spec => { if (source.url.paths) { // We filter out all deprecated url patterns here. - const paths = source.url.paths.filter(path => !path.deprecated); + const paths = source.url.paths.filter((path) => !path.deprecated); patterns = convertPaths(paths); - paths.forEach(pathsObject => { - pathsObject.methods.forEach(method => methodSet.add(method)); + paths.forEach((pathsObject) => { + pathsObject.methods.forEach((method) => methodSet.add(method)); if (pathsObject.parts) { for (const partName of Object.keys(pathsObject.parts)) { urlComponents[partName] = pathsObject.parts[partName]; @@ -79,7 +79,7 @@ module.exports = spec => { if (Object.keys(urlComponents).length) { const components = convertParts(urlComponents); const hasComponents = - Object.keys(components).filter(c => { + Object.keys(components).filter((c) => { return Boolean(components[c]); }).length > 0; if (hasComponents) { diff --git a/packages/kbn-spec-to-console/lib/convert/methods.js b/packages/kbn-spec-to-console/lib/convert/methods.js index b4ab8f467ae1f4..89d193dd380711 100644 --- a/packages/kbn-spec-to-console/lib/convert/methods.js +++ b/packages/kbn-spec-to-console/lib/convert/methods.js @@ -17,6 +17,6 @@ * under the License. */ -module.exports = methods => { +module.exports = (methods) => { return methods; }; diff --git a/packages/kbn-spec-to-console/lib/convert/params.js b/packages/kbn-spec-to-console/lib/convert/params.js index 0d1747ae4f6856..00169b12322ed7 100644 --- a/packages/kbn-spec-to-console/lib/convert/params.js +++ b/packages/kbn-spec-to-console/lib/convert/params.js @@ -17,9 +17,9 @@ * under the License. */ -module.exports = params => { +module.exports = (params) => { const result = {}; - Object.keys(params).forEach(param => { + Object.keys(params).forEach((param) => { const { type, description = '', options = [] } = params[param]; const [, defaultValue] = description.match(/\(default: (.*)\)/) || []; switch (type) { @@ -35,7 +35,7 @@ module.exports = params => { case 'enum': // This is to clean up entries like: "d (Days)". We only want the "d" part. if (param === 'time') { - result[param] = options.map(option => option.split(' ')[0]); + result[param] = options.map((option) => option.split(' ')[0]); } else { result[param] = options; } diff --git a/packages/kbn-spec-to-console/lib/convert/parts.js b/packages/kbn-spec-to-console/lib/convert/parts.js index 040d04a0c1dc4d..96cd3c94e796d4 100644 --- a/packages/kbn-spec-to-console/lib/convert/parts.js +++ b/packages/kbn-spec-to-console/lib/convert/parts.js @@ -19,9 +19,9 @@ const replacePattern = require('../replace_pattern'); -module.exports = parts => { +module.exports = (parts) => { const result = {}; - Object.keys(parts).forEach(part => { + Object.keys(parts).forEach((part) => { const key = replacePattern(part, { exact: true }); const options = parts[part].options; if (options && options.length) { diff --git a/packages/kbn-spec-to-console/lib/convert/paths.js b/packages/kbn-spec-to-console/lib/convert/paths.js index 6c65bf48b9b063..af8897c2782f26 100644 --- a/packages/kbn-spec-to-console/lib/convert/paths.js +++ b/packages/kbn-spec-to-console/lib/convert/paths.js @@ -19,8 +19,8 @@ const replacePattern = require('../replace_pattern'); -module.exports = patterns => { - return patterns.map(patternObject => { +module.exports = (patterns) => { + return patterns.map((patternObject) => { return replacePattern(patternObject.path, { brackets: true }); }); }; diff --git a/packages/kbn-spec-to-console/lib/replace_pattern.js b/packages/kbn-spec-to-console/lib/replace_pattern.js index 29d16be3cc70f5..4da75db78086d0 100644 --- a/packages/kbn-spec-to-console/lib/replace_pattern.js +++ b/packages/kbn-spec-to-console/lib/replace_pattern.js @@ -21,7 +21,7 @@ const map = require('./static/map_interpolation'); module.exports = (pattern, { brackets, exact } = {}) => { let newPattern = pattern; - Object.keys(map).forEach(key => { + Object.keys(map).forEach((key) => { const replaceFrom = brackets ? `{${key}}` : key; const replaceTo = brackets ? `{${map[key]}}` : map[key]; if (exact) { diff --git a/packages/kbn-spec-to-console/package.json b/packages/kbn-spec-to-console/package.json index a6b3e8f96f7dba..ebbf244eb2e101 100644 --- a/packages/kbn-spec-to-console/package.json +++ b/packages/kbn-spec-to-console/package.json @@ -18,7 +18,7 @@ "homepage": "https://github.com/jbudz/spec-to-console#readme", "devDependencies": { "jest": "^24.9.0", - "prettier": "^1.19.1" + "prettier": "^2.0.5" }, "dependencies": { "commander": "^3.0.0", diff --git a/packages/kbn-storybook/index.js b/packages/kbn-storybook/index.js index b595de8ea1c07c..c7dae20902f1af 100644 --- a/packages/kbn-storybook/index.js +++ b/packages/kbn-storybook/index.js @@ -27,7 +27,7 @@ const { generateStorybookEntry } = require('./lib/storybook_entry'); const { REPO_ROOT, ASSET_DIR, CURRENT_CONFIG } = require('./lib/constants'); const { buildDll } = require('./lib/dll'); -exports.runStorybookCli = config => { +exports.runStorybookCli = (config) => { const { name, storyGlobs } = config; run( async ({ flags, log, procRunner }) => { diff --git a/packages/kbn-storybook/lib/storybook_entry.js b/packages/kbn-storybook/lib/storybook_entry.js index dececef47f40e4..9eb1b0a458c6a3 100644 --- a/packages/kbn-storybook/lib/storybook_entry.js +++ b/packages/kbn-storybook/lib/storybook_entry.js @@ -37,7 +37,7 @@ const STORE_ENTRY_DIR = dirname(STORY_ENTRY_PATH); exports.generateStorybookEntry = ({ log, storyGlobs }) => { const globs = ['built_assets/css/**/*.light.css', ...storyGlobs]; log.info('Storybook globs:\n', globs); - const norm = p => normalize(relative(STORE_ENTRY_DIR, p)); + const norm = (p) => normalize(relative(STORE_ENTRY_DIR, p)); return Rx.defer(() => glob(globs, { @@ -46,20 +46,20 @@ exports.generateStorybookEntry = ({ log, storyGlobs }) => { onlyFiles: true, }) ).pipe( - map(paths => { + map((paths) => { log.info('Discovered Storybook entry points:\n', paths); return new Set(paths.map(norm)); }), mergeMap( - paths => - new Rx.Observable(observer => { + (paths) => + new Rx.Observable((observer) => { observer.next(paths); const chokidar = watch(globs, { cwd: REPO_ROOT }) - .on('add', path => { + .on('add', (path) => { observer.next(paths.add(norm(resolve(REPO_ROOT, path)))); }) - .on('unlink', path => { + .on('unlink', (path) => { observer.next(paths.delete(norm(resolve(REPO_ROOT, path)))); }); diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json index 0b38554f7806c0..f865a9fb474969 100644 --- a/packages/kbn-storybook/package.json +++ b/packages/kbn-storybook/package.json @@ -18,14 +18,14 @@ "fast-glob": "2.2.7", "glob-watcher": "5.0.3", "jest-specific-snapshot": "2.0.0", - "jest-styled-components": "6.3.1", + "jest-styled-components": "^7.0.2", "mkdirp": "0.5.1", "mini-css-extract-plugin": "0.7.0", "normalize-path": "3.0.0", "react-docgen-typescript-loader": "3.1.0", "rxjs": "6.5.2", "serve-static": "1.14.1", - "styled-components": "^3", + "styled-components": "^5.1.0", "webpack": "^4.41.5" } } \ No newline at end of file diff --git a/packages/kbn-storybook/storybook_config/middleware.js b/packages/kbn-storybook/storybook_config/middleware.js index 046758948b2cff..9410bb66030d92 100644 --- a/packages/kbn-storybook/storybook_config/middleware.js +++ b/packages/kbn-storybook/storybook_config/middleware.js @@ -21,6 +21,6 @@ const serve = require('serve-static'); const path = require('path'); // Extend the Storybook Middleware to include a route to access Legacy UI assets -module.exports = function(router) { +module.exports = function (router) { router.get('/ui', serve(path.resolve(__dirname, '../../../src/core/server/core_app/assets'))); }; diff --git a/packages/kbn-storybook/storybook_config/mocks/noop.js b/packages/kbn-storybook/storybook_config/mocks/noop.js index aaddfb2ed8ac31..e78d222eaa560c 100755 --- a/packages/kbn-storybook/storybook_config/mocks/noop.js +++ b/packages/kbn-storybook/storybook_config/mocks/noop.js @@ -17,4 +17,4 @@ * under the License. */ -export default function() {} +export default function () {} diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js index 779d8a41536445..2dd051882bb4bc 100644 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ b/packages/kbn-storybook/storybook_config/webpack.config.js @@ -29,7 +29,7 @@ const { currentConfig } = require('../../../built_assets/storybook/current.confi module.exports = async ({ config }) => { // Find and alter the CSS rule to replace the Kibana public path string with a path // to the route we've added in middleware.js - const cssRule = config.module.rules.find(rule => rule.test.source.includes('.css$')); + const cssRule = config.module.rules.find((rule) => rule.test.source.includes('.css$')); cssRule.use.push({ loader: 'string-replace-loader', options: { diff --git a/packages/kbn-test-subj-selector/__tests__/index.js b/packages/kbn-test-subj-selector/__tests__/index.js index e18405b99ae52f..23165cefec94ab 100755 --- a/packages/kbn-test-subj-selector/__tests__/index.js +++ b/packages/kbn-test-subj-selector/__tests__/index.js @@ -20,8 +20,8 @@ const testSubjSelector = require('../'); const expect = require('@kbn/expect'); -describe('testSubjSelector()', function() { - it('converts subjectSelectors to cssSelectors', function() { +describe('testSubjSelector()', function () { + it('converts subjectSelectors to cssSelectors', function () { expect(testSubjSelector('foo bar')).to.eql('[data-test-subj="foo bar"]'); expect(testSubjSelector('foo > bar')).to.eql('[data-test-subj="foo"] [data-test-subj="bar"]'); expect(testSubjSelector('foo > bar baz')).to.eql( diff --git a/packages/kbn-test-subj-selector/index.js b/packages/kbn-test-subj-selector/index.js index 3984c15c00fefa..2be59d78dc5efb 100755 --- a/packages/kbn-test-subj-selector/index.js +++ b/packages/kbn-test-subj-selector/index.js @@ -42,12 +42,7 @@ module.exports = function testSubjSelector(selector) { while (terms.length) { const term = terms.shift(); // split each term by joins/& and map to css selectors - cssSelectors.push( - term - .split('&') - .map(termToCssSelector) - .join('') - ); + cssSelectors.push(term.split('&').map(termToCssSelector).join('')); } return cssSelectors.join(' '); diff --git a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts index 0c824754b1237d..7cbeb18a5ebd42 100644 --- a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts +++ b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts @@ -25,12 +25,8 @@ import { createPatch } from 'diff'; // turns out Jest can't encode xml diffs in their JUnit reports... expect.addSnapshotSerializer({ - test: v => typeof v === 'string' && (v.includes('<') || v.includes('>')), - print: v => - v - .replace(//g, '›') - .replace(/^\s+$/gm, ''), + test: (v) => typeof v === 'string' && (v.includes('<') || v.includes('>')), + print: (v) => v.replace(//g, '›').replace(/^\s+$/gm, ''), }); jest.mock('fs', () => { diff --git a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.ts b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.ts index 32ea5fa0f90339..6bc7556db8a475 100644 --- a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.ts +++ b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.ts @@ -49,7 +49,7 @@ export async function addMessagesToReport(options: { for (const testCase of makeFailedTestCaseIter(report)) { const { classname, name } = testCase.$; const messageList = messages - .filter(u => u.classname === classname && u.name === name) + .filter((u) => u.classname === classname && u.name === name) .reduce((acc, u) => `${acc}\n - ${u.message}`, ''); if (!messageList) { @@ -76,7 +76,7 @@ export async function addMessagesToReport(options: { const xml = builder .buildObject(report) .split('\n') - .map(line => (line.trim() === '' ? '' : line)) + .map((line) => (line.trim() === '' ? '' : line)) .join('\n'); if (dryRun) { diff --git a/packages/kbn-test/src/failed_tests_reporter/github_api.ts b/packages/kbn-test/src/failed_tests_reporter/github_api.ts index 7da79b5b67e63f..a0e3bcafdf1967 100644 --- a/packages/kbn-test/src/failed_tests_reporter/github_api.ts +++ b/packages/kbn-test/src/failed_tests_reporter/github_api.ts @@ -233,7 +233,7 @@ export class GithubApi { this.log.error(`Unable to reach github, waiting ${waitMs}ms to retry`); } - await new Promise(resolve => setTimeout(resolve, waitMs)); + await new Promise((resolve) => setTimeout(resolve, waitMs)); return await this.request( { ...options, diff --git a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts index 9324f9eb42aa5f..b298c08f162bf3 100644 --- a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts +++ b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts @@ -100,7 +100,7 @@ export function runFailedTestsReporterCli() { } let existingIssue: GithubIssueMini | undefined = await githubApi.findFailedTestIssue( - i => + (i) => getIssueMetadata(i.body, 'test.class') === failure.classname && getIssueMetadata(i.body, 'test.name') === failure.name ); diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js index 3c8daf4154236d..133f4d2feb53e6 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js @@ -26,7 +26,7 @@ import { REPO_ROOT } from '@kbn/dev-utils'; const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); const BASIC_CONFIG = require.resolve('../fixtures/simple_project/config.js'); -describe('basic config file with a single app and test', function() { +describe('basic config file with a single app and test', function () { this.timeout(60 * 1000); it('runs and prints expected output', () => { diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js index d6e7b1ac58aa42..12e28d2702c5a6 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js @@ -27,7 +27,7 @@ import { REPO_ROOT } from '@kbn/dev-utils'; const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); const FAILURE_HOOKS_CONFIG = require.resolve('../fixtures/failure_hooks/config.js'); -describe('failure hooks', function() { +describe('failure hooks', function () { this.timeout(60 * 1000); it('runs and prints expected output', () => { diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts index 276a51c3a6a997..fd5ee5ad3ae440 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli.ts @@ -87,7 +87,7 @@ export function runFtrCli() { } }; - process.on('unhandledRejection', err => + process.on('unhandledRejection', (err) => teardown( err instanceof Error ? err : new Error(`non-Error type rejection value: ${inspect(err)}`) ) diff --git a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts index 3a66ba22ccf3d4..03d4d7643607f3 100644 --- a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts +++ b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts @@ -89,7 +89,7 @@ export class FunctionalTestRunner { // promise-like objects which never resolve, essentially disabling them // allowing us to load the test files and populate the mocha suites const readStubbedProviderSpec = (type: string, providers: any) => - readProviderSpec(type, providers).map(p => ({ + readProviderSpec(type, providers).map((p) => ({ ...p, fn: () => ({ then: () => {}, diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/config.ts b/packages/kbn-test/src/functional_test_runner/lib/config/config.ts index ad9247523797a5..e38520f00e45b6 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/config.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/config.ts @@ -114,7 +114,7 @@ export class Config { throw new Error(`Unknown config key "${key}"`); } - return cloneDeep(get(this[$values], key, defaultValue), v => { + return cloneDeep(get(this[$values], key, defaultValue), (v) => { if (typeof v === 'function') { return v; } @@ -122,7 +122,7 @@ export class Config { } public getAll() { - return cloneDeep(this[$values], v => { + return cloneDeep(this[$values], (v) => { if (typeof v === 'function') { return v; } diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index f4b91d154cbb88..29ec28175a8519 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -30,12 +30,8 @@ const INSPECTING = const urlPartsSchema = () => Joi.object() .keys({ - protocol: Joi.string() - .valid('http', 'https') - .default('http'), - hostname: Joi.string() - .hostname() - .default('localhost'), + protocol: Joi.string().valid('http', 'https').default('http'), + hostname: Joi.string().hostname().default('localhost'), port: Joi.number(), auth: Joi.string().regex(/^[^:]+:.+$/, 'username and password separated by a colon'), username: Joi.string(), @@ -66,33 +62,21 @@ export const schema = Joi.object() suiteFiles: Joi.object() .keys({ - include: Joi.array() - .items(Joi.string()) - .default([]), - exclude: Joi.array() - .items(Joi.string()) - .default([]), + include: Joi.array().items(Joi.string()).default([]), + exclude: Joi.array().items(Joi.string()).default([]), }) .default(), suiteTags: Joi.object() .keys({ - include: Joi.array() - .items(Joi.string()) - .default([]), - exclude: Joi.array() - .items(Joi.string()) - .default([]), + include: Joi.array().items(Joi.string()).default([]), + exclude: Joi.array().items(Joi.string()).default([]), }) .default(), - services: Joi.object() - .pattern(ID_PATTERN, Joi.func().required()) - .default(), + services: Joi.object().pattern(ID_PATTERN, Joi.func().required()).default(), - pageObjects: Joi.object() - .pattern(ID_PATTERN, Joi.func().required()) - .default(), + pageObjects: Joi.object().pattern(ID_PATTERN, Joi.func().required()).default(), timeouts: Joi.object() .keys({ @@ -135,9 +119,7 @@ export const schema = Joi.object() browser: Joi.object() .keys({ - type: Joi.string() - .valid('chrome', 'firefox', 'ie', 'msedge') - .default('chrome'), + type: Joi.string().valid('chrome', 'firefox', 'ie', 'msedge').default('chrome'), logPollingMs: Joi.number().default(100), }) @@ -210,9 +192,7 @@ export const schema = Joi.object() .default(), // definition of apps that work with `common.navigateToApp()` - apps: Joi.object() - .pattern(ID_PATTERN, appUrlPartsSchema()) - .default(), + apps: Joi.object().pattern(ID_PATTERN, appUrlPartsSchema()).default(), // settings for the esArchiver module esArchiver: Joi.object() diff --git a/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts b/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts index be033e063fb9d3..fdf8b3c0ddfa8e 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts @@ -39,7 +39,7 @@ export class FailureMetadata { ); } - lifecycle.beforeEachRunnable.add(runnable => { + lifecycle.beforeEachRunnable.add((runnable) => { this.currentRunnable = runnable; }); } @@ -57,7 +57,7 @@ export class FailureMetadata { } addMessages(messages: string[]) { - this.add(current => ({ + this.add((current) => ({ messages: [...(Array.isArray(current.messages) ? current.messages : []), ...messages], })); } @@ -76,7 +76,7 @@ export class FailureMetadata { const slash = prefix.endsWith('/') ? '' : '/'; const urlPath = Path.relative(REPO_ROOT, repoPath) .split(Path.sep) - .map(c => encodeURIComponent(c)) + .map((c) => encodeURIComponent(c)) .join('/'); if (urlPath.startsWith('..')) { @@ -91,7 +91,7 @@ export class FailureMetadata { url, }; - this.add(current => ({ + this.add((current) => ({ screenshots: [...(Array.isArray(current.screenshots) ? current.screenshots : []), screenshot], })); diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_event.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_event.ts index 22b73634543612..ce242d44009f23 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_event.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_event.ts @@ -57,7 +57,7 @@ export class LifecycleEvent { } try { - await Promise.all(this.handlers.map(async fn => await fn(...args))); + await Promise.all(this.handlers.map(async (fn) => await fn(...args))); } finally { this.afterSubj.next(undefined); if (this.options.singular) { diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts index 94dd76884f2cab..d17c5503c42f84 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts @@ -104,7 +104,7 @@ describe('without randomness', () => { const handler = jest.fn(async () => { order.push('handler start'); - await new Promise(resolve => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 100)); order.push('handler done'); }); phase.add(handler); @@ -124,10 +124,10 @@ describe('without randomness', () => { const phase = new LifecyclePhase({ singular: true }); const beforeNotifs: Array> = []; - phase.before$.pipe(materialize()).subscribe(n => beforeNotifs.push(n)); + phase.before$.pipe(materialize()).subscribe((n) => beforeNotifs.push(n)); const afterNotifs: Array> = []; - phase.after$.pipe(materialize()).subscribe(n => afterNotifs.push(n)); + phase.after$.pipe(materialize()).subscribe((n) => afterNotifs.push(n)); await phase.trigger(); expect(beforeNotifs).toMatchInlineSnapshot(` diff --git a/packages/kbn-test/src/functional_test_runner/lib/load_tracer.ts b/packages/kbn-test/src/functional_test_runner/lib/load_tracer.ts index 26a0e9617a7c70..588e32b5d274cb 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/load_tracer.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/load_tracer.ts @@ -22,7 +22,7 @@ const globalLoadPath: Array<{ ident: string; description: string }> = []; function getPath(startAt = 0) { return globalLoadPath .slice(startAt) - .map(step => step.description) + .map((step) => step.description) .join(' -> '); } @@ -49,7 +49,7 @@ function addPathToMessage(message: string, startAt?: number) { * @return {Any} the value produced by load() */ export function loadTracer(ident: any, description: string, load: () => Promise | void) { - const isCircular = globalLoadPath.find(step => step.ident === ident); + const isCircular = globalLoadPath.find((step) => step.ident === ident); if (isCircular) { throw new Error(addPathToMessage(`Circular reference to "${description}"`)); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/assignment_proxy.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/assignment_proxy.js index 5c08d566d3d73a..ecf8f7af87ed8e 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/assignment_proxy.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/assignment_proxy.js @@ -31,7 +31,7 @@ export function createAssignmentProxy(object, interceptor) { get(target, property) { if (property === 'revertProxiedAssignments') { - return function() { + return function () { for (const [property, value] of originalValues) { object[property] = value; } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js index 1cac852a7e7130..5d3d8fe7d759bb 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js @@ -57,12 +57,12 @@ export function decorateMochaUi(lifecycle, context) { throw new Error(`Unexpected arguments to ${name}(${argumentsList.join(', ')})`); } - argumentsList[1] = function() { + argumentsList[1] = function () { before(async () => { await lifecycle.beforeTestSuite.trigger(this); }); - this.tags = tags => { + this.tags = (tags) => { this._tags = [].concat(this._tags || [], tags); }; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.js index 302d43fac3e614..f7aaabd5a4495a 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.js @@ -30,7 +30,7 @@ export function filterSuitesByTags({ log, mocha, include, exclude }) { mocha.excludedTests = []; // collect all the tests from some suite, including it's children - const collectTests = suite => + const collectTests = (suite) => suite.suites.reduce((acc, s) => acc.concat(collectTests(s)), suite.tests); // if include tags were provided, filter the tree once to @@ -38,8 +38,10 @@ export function filterSuitesByTags({ log, mocha, include, exclude }) { if (include.length) { log.info('Only running suites (and their sub-suites) if they include the tag(s):', include); - const isIncluded = suite => (!suite._tags ? false : suite._tags.some(t => include.includes(t))); - const isChildIncluded = suite => suite.suites.some(s => isIncluded(s) || isChildIncluded(s)); + const isIncluded = (suite) => + !suite._tags ? false : suite._tags.some((t) => include.includes(t)); + const isChildIncluded = (suite) => + suite.suites.some((s) => isIncluded(s) || isChildIncluded(s)); (function recurse(parentSuite) { const children = parentSuite.suites; @@ -73,7 +75,7 @@ export function filterSuitesByTags({ log, mocha, include, exclude }) { if (exclude.length) { log.info('Filtering out any suites that include the tag(s):', exclude); - const isNotExcluded = suite => !suite._tags || !suite._tags.some(t => exclude.includes(t)); + const isNotExcluded = (suite) => !suite._tags || !suite._tags.some((t) => exclude.includes(t)); (function recurse(parentSuite) { const children = parentSuite.suites; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js index 9901f62ae71cf3..6ecfadfd25d6d5 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js @@ -26,21 +26,21 @@ import Test from 'mocha/lib/test'; import { filterSuitesByTags } from './filter_suites_by_tags'; function setup({ include, exclude }) { - return new Promise(resolve => { + return new Promise((resolve) => { const history = []; const mocha = new Mocha({ reporter: class { constructor(runner) { - runner.on('hook', hook => { + runner.on('hook', (hook) => { history.push(`hook: ${hook.fullTitle()}`); }); - runner.on('pass', test => { + runner.on('pass', (test) => { history.push(`test: ${test.fullTitle()}`); }); - runner.on('suite', suite => { + runner.on('suite', (suite) => { history.push(`suite: ${suite.fullTitle()}`); }); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js index 6ee65b1b7e3941..5c23be6361866d 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js @@ -32,7 +32,7 @@ import { decorateMochaUi } from './decorate_mocha_ui'; * @return {undefined} - mutates mocha, no return value */ export const loadTestFiles = ({ mocha, log, lifecycle, providers, paths, updateBaselines }) => { - const innerLoadTestFile = path => { + const innerLoadTestFile = (path) => { if (typeof path !== 'string' || !isAbsolute(path)) { throw new TypeError('loadTestFile() only accepts absolute paths'); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js index 0e8c1bc121e155..90bea1c3aa2931 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js @@ -54,7 +54,7 @@ export function MochaReporterProvider({ getService }) { if (config.get('junit.enabled') && config.get('junit.reportName')) { setupJUnitReportGeneration(runner, { reportName: config.get('junit.reportName'), - getTestMetadata: t => failureMetadata.get(t), + getTestMetadata: (t) => failureMetadata.get(t), }); } } @@ -76,7 +76,7 @@ export function MochaReporterProvider({ getService }) { new ToolingLogTextWriter({ level: 'debug', writeTo: { - write: line => { + write: (line) => { // if the current runnable is a beforeEach hook then // `runner.suite` is set to the suite that defined the // hook, rather than the suite executing, so instead we @@ -104,7 +104,7 @@ export function MochaReporterProvider({ getService }) { log.write(''); }; - onHookStart = hook => { + onHookStart = (hook) => { log.write(`-> ${colors.suite(hook.title)}`); log.indent(2); }; @@ -113,7 +113,7 @@ export function MochaReporterProvider({ getService }) { log.indent(-2); }; - onSuiteStart = suite => { + onSuiteStart = (suite) => { if (!suite.root) { log.write('-: ' + colors.suite(suite.title)); } @@ -127,28 +127,28 @@ export function MochaReporterProvider({ getService }) { } }; - onTestStart = test => { + onTestStart = (test) => { log.write(`-> ${test.title}`); log.indent(2); }; - onTestEnd = test => { + onTestEnd = (test) => { snapshotLogsForRunnable(test); log.indent(-2); }; - onPending = test => { + onPending = (test) => { log.write('-> ' + colors.pending(test.title)); log.indent(2); }; - onPass = test => { + onPass = (test) => { const time = colors.speed(test.speed, ` (${ms(test.duration)})`); const pass = colors.pass(`${symbols.ok} pass`); log.write(`- ${pass} ${time} "${test.fullTitle()}"`); }; - onFail = runnable => { + onFail = (runnable) => { // NOTE: this is super gross // // - I started by trying to extract the Base.list() logic from mocha @@ -173,8 +173,8 @@ export function MochaReporterProvider({ getService }) { // drop the first two lines, (empty + test title) .slice(2) // move leading colors behind leading spaces - .map(line => line.replace(/^((?:\[.+m)+)(\s+)/, '$2$1')) - .map(line => ` ${line}`) + .map((line) => line.replace(/^((?:\[.+m)+)(\s+)/, '$2$1')) + .map((line) => ` ${line}`) .join('\n') ); diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts b/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts index 654f588fda8580..a23a5fb1407a01 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts @@ -39,7 +39,7 @@ export async function runTests(lifecycle: Lifecycle, mocha: Mocha) { if (!runComplete) runner.abort(); }); - return new Promise(resolve => { + return new Promise((resolve) => { const respond = () => resolve(runner.failures); // if there are no tests, mocha.run() is sync diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js index 61851cece0e8ff..3ac7a50cd28ea0 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js @@ -42,7 +42,7 @@ export async function setupMocha(lifecycle, log, config, providers) { }); // global beforeEach hook in root suite triggers before all others - mocha.suite.beforeEach('global before each', async function() { + mocha.suite.beforeEach('global before each', async function () { await lifecycle.beforeEachTest.trigger(this.currentTest); }); @@ -62,15 +62,15 @@ export async function setupMocha(lifecycle, log, config, providers) { filterSuitesByTags({ log, mocha, - include: config.get('suiteFiles.include').map(file => relative(REPO_ROOT, file)), - exclude: config.get('suiteFiles.exclude').map(file => relative(REPO_ROOT, file)), + include: config.get('suiteFiles.include').map((file) => relative(REPO_ROOT, file)), + exclude: config.get('suiteFiles.exclude').map((file) => relative(REPO_ROOT, file)), }); filterSuitesByTags({ log, mocha, - include: config.get('suiteTags.include').map(tag => tag.replace(/-\d+$/, '')), - exclude: config.get('suiteTags.exclude').map(tag => tag.replace(/-\d+$/, '')), + include: config.get('suiteTags.include').map((tag) => tag.replace(/-\d+$/, '')), + exclude: config.get('suiteTags.exclude').map((tag) => tag.replace(/-\d+$/, '')), }); return mocha; diff --git a/packages/kbn-test/src/functional_test_runner/lib/providers/async_instance.ts b/packages/kbn-test/src/functional_test_runner/lib/providers/async_instance.ts index 7bb1b2bc153c1b..2d5644fbad290a 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/providers/async_instance.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/providers/async_instance.ts @@ -34,7 +34,7 @@ export const createAsyncInstance = ( ): AsyncInstance => { let instance: T | symbol = INITIALIZING; - const initPromise = promiseForValue.then(v => (instance = v)); + const initPromise = promiseForValue.then((v) => (instance = v)); const loadingTarget = { init() { return initPromise; diff --git a/packages/kbn-test/src/functional_test_runner/lib/providers/provider_collection.ts b/packages/kbn-test/src/functional_test_runner/lib/providers/provider_collection.ts index f9ad86be634fc2..c58747e07dcf43 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/providers/provider_collection.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/providers/provider_collection.ts @@ -37,7 +37,7 @@ export class ProviderCollection { public getPageObjects = (names: string[]) => { const pageObjects: Record = {}; - names.forEach(name => (pageObjects[name] = this.getPageObject(name))); + names.forEach((name) => (pageObjects[name] = this.getPageObject(name))); return pageObjects; }; @@ -78,7 +78,7 @@ export class ProviderCollection { } private findProvider(type: string, name: string) { - return this.providers.find(p => p.type === type && p.name === name); + return this.providers.find((p) => p.type === type && p.name === name); } private getProvider(type: string, name: string) { diff --git a/packages/kbn-test/src/functional_test_runner/lib/providers/read_provider_spec.ts b/packages/kbn-test/src/functional_test_runner/lib/providers/read_provider_spec.ts index be8e25f102b095..a29b220bc603b7 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/providers/read_provider_spec.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/providers/read_provider_spec.ts @@ -21,7 +21,7 @@ export type Providers = ReturnType; export type Provider = Providers extends Array ? X : unknown; export function readProviderSpec(type: string, providers: Record any>) { - return Object.keys(providers).map(name => { + return Object.keys(providers).map((name) => { return { type, name, diff --git a/packages/kbn-test/src/functional_test_runner/lib/providers/verbose_instance.ts b/packages/kbn-test/src/functional_test_runner/lib/providers/verbose_instance.ts index 93a87f3496b54c..1967e98306d421 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/providers/verbose_instance.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/providers/verbose_instance.ts @@ -23,7 +23,7 @@ import { ToolingLog } from '@kbn/dev-utils'; function printArgs(args: any[]): string { return args - .map(arg => { + .map((arg) => { if (typeof arg === 'string' || typeof arg === 'number' || arg instanceof Date) { return inspect(arg); } @@ -42,7 +42,7 @@ export function createVerboseInstance( name: string, instance: { [k: string]: any; [i: number]: any } ) { - if (!log.getWriters().some(l => (l as any).level.flags.verbose)) { + if (!log.getWriters().some((l) => (l as any).level.flags.verbose)) { return instance; } @@ -54,7 +54,7 @@ export function createVerboseInstance( return value; } - return function(this: any, ...args: any[]) { + return function (this: any, ...args: any[]) { log.verbose(`${name}.${prop}(${printArgs(args)})`); log.indent(2); diff --git a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts index b6c2c0a6d511d1..f879408bf2bebb 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts @@ -145,8 +145,8 @@ describe('SuiteTracker', () => { const { suiteTracker } = await runLifecycleWithMocks([root, parent, withTests]); const suites = suiteTracker.getAllFinishedSuites(); - const finishedRoot = suites.find(s => s.title === 'root'); - const finishedWithTests = suites.find(s => s.title !== 'root'); + const finishedRoot = suites.find((s) => s.title === 'root'); + const finishedWithTests = suites.find((s) => s.title !== 'root'); expect(finishedRoot).toBeTruthy(); expect(finishedRoot?.hasTests).toBeFalsy(); diff --git a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts index 8967251ea78de7..b346be2d58dad2 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts @@ -70,7 +70,7 @@ export class SuiteTracker { const config = relative(REPO_ROOT, configPathAbsolute); - lifecycle.beforeTestSuite.add(suite => { + lifecycle.beforeTestSuite.add((suite) => { const tracked = this.getTracked(suite); tracked.startTime = new Date(); }); @@ -92,7 +92,7 @@ export class SuiteTracker { lifecycle.testFailure.add(handleFailure); lifecycle.testHookFailure.add(handleFailure); - lifecycle.afterTestSuite.add(suite => { + lifecycle.afterTestSuite.add((suite) => { const tracked = this.getTracked(suite); tracked.endTime = new Date(); diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js index 7d2414305de8e7..94d510915d8e59 100644 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js +++ b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js @@ -73,8 +73,8 @@ const options = { export function displayHelp() { const helpOptions = Object.keys(options) - .filter(name => name !== '_') - .map(name => { + .filter((name) => name !== '_') + .map((name) => { const option = options[name]; return { ...option, @@ -82,7 +82,7 @@ export function displayHelp() { default: option.defaultHelp || '', }; }) - .map(option => { + .map((option) => { return `--${option.usage.padEnd(28)} ${option.desc} ${option.default}`; }) .join(`\n `); @@ -149,7 +149,7 @@ export function processOptions(userOptions, defaultConfigPaths) { return { ...userOptions, - configs: configs.map(c => resolve(c)), + configs: configs.map((c) => resolve(c)), createLogger, extraKbnOpts: userOptions._, }; diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js b/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js index 27335739d290ee..cf49fc77e479fd 100644 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js +++ b/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js @@ -30,7 +30,7 @@ import { processOptions, displayHelp } from './args'; * if no config option is passed */ export async function runTestsCli(defaultConfigPaths) { - await runCli(displayHelp, async userOptions => { + await runCli(displayHelp, async (userOptions) => { const options = processOptions(userOptions, defaultConfigPaths); await runTests(options); }); diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/args.js b/packages/kbn-test/src/functional_tests/cli/start_servers/args.js index c221ad42fcad19..e604e86de8b3a5 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/args.js +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/args.js @@ -45,8 +45,8 @@ const options = { export function displayHelp() { const helpOptions = Object.keys(options) - .filter(name => name !== '_') - .map(name => { + .filter((name) => name !== '_') + .map((name) => { const option = options[name]; return { ...option, @@ -54,7 +54,7 @@ export function displayHelp() { default: option.defaultHelp || '', }; }) - .map(option => { + .map((option) => { return `--${option.usage.padEnd(30)} ${option.desc} ${option.default}`; }) .join(`\n `); diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js index 5716441798aa41..d4499ee76e313f 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js @@ -27,7 +27,7 @@ import { processOptions, displayHelp } from './args'; * if no config option is passed */ export async function startServersCli(defaultConfigPath) { - await runCli(displayHelp, async userOptions => { + await runCli(displayHelp, async (userOptions) => { const options = processOptions(userOptions, defaultConfigPath); await startServers(options); }); diff --git a/packages/kbn-test/src/functional_tests/lib/run_cli.js b/packages/kbn-test/src/functional_tests/lib/run_cli.js index 56f6f36f5388f7..51a970e1a305dc 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_cli.js +++ b/packages/kbn-test/src/functional_tests/lib/run_cli.js @@ -53,12 +53,7 @@ export async function runCli(getHelpText, run) { if (!(error instanceof CliError)) { // first line in the stack trace is the message, skip it as we log it directly and color it red if (error.stack) { - console.log( - error.stack - .split('\n') - .slice(1) - .join('\n') - ); + console.log(error.stack.split('\n').slice(1).join('\n')); } else { console.log(' (no stack trace)'); } diff --git a/packages/kbn-test/src/functional_tests/lib/run_cli.test.js b/packages/kbn-test/src/functional_tests/lib/run_cli.test.js index 235f50f0d9dd79..959f9659175306 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_cli.test.js +++ b/packages/kbn-test/src/functional_tests/lib/run_cli.test.js @@ -25,7 +25,7 @@ const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => {}); const actualProcessArgv = process.argv; -const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); beforeEach(() => { process.argv = actualProcessArgv.slice(0, 2); @@ -72,7 +72,7 @@ it('waits for promise returned from run function to resolve before resolving', a let resolveMockRun; const mockRun = jest.fn().mockImplementation( () => - new Promise(resolve => { + new Promise((resolve) => { resolveMockRun = resolve; }) ); diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js index 5f58190078f0d2..3d174791fffc13 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js @@ -63,7 +63,7 @@ export async function runElasticsearch({ config, options }) { function getRelativeCertificateAuthorityPath(esConfig = []) { const caConfig = esConfig.find( - config => config.indexOf('--elasticsearch.ssl.certificateAuthorities') === 0 + (config) => config.indexOf('--elasticsearch.ssl.certificateAuthorities') === 0 ); return caConfig ? caConfig.split('=')[1] : undefined; } diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js index a5744d64988014..fb9f8f7a52408c 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js @@ -58,9 +58,9 @@ function collectCliArgs(config, { installDir, extraKbnOpts }) { return pipe( serverArgs, - args => (installDir ? args.filter(a => a !== '--oss') : args), - args => (installDir ? [...buildArgs, ...args] : [KIBANA_EXEC_PATH, ...sourceArgs, ...args]), - args => args.concat(extraKbnOpts || []) + (args) => (installDir ? args.filter((a) => a !== '--oss') : args), + (args) => (installDir ? [...buildArgs, ...args] : [KIBANA_EXEC_PATH, ...sourceArgs, ...args]), + (args) => args.concat(extraKbnOpts || []) ); } @@ -79,7 +79,7 @@ function filterCliArgs(args) { // the current val. If so, skip this val. if ( !allowsDuplicate(val) && - findIndexFrom(args, ++ind, opt => opt.split('=')[0] === val.split('=')[0]) > -1 + findIndexFrom(args, ++ind, (opt) => opt.split('=')[0] === val.split('=')[0]) > -1 ) { return acc; } @@ -112,7 +112,7 @@ function isBasePathSettingOverridden(args, val, ind) { const basePathKeys = ['--no-base-path', '--server.basePath']; if (basePathKeys.includes(key)) { - if (findIndexFrom(args, ++ind, opt => basePathKeys.includes(opt.split('=')[0])) > -1) { + if (findIndexFrom(args, ++ind, (opt) => basePathKeys.includes(opt.split('=')[0])) > -1) { return true; } } diff --git a/packages/kbn-test/src/functional_tests/tasks.js b/packages/kbn-test/src/functional_tests/tasks.js index 8645923a13d30d..7d4fc84d47bda9 100644 --- a/packages/kbn-test/src/functional_tests/tasks.js +++ b/packages/kbn-test/src/functional_tests/tasks.js @@ -34,7 +34,7 @@ import { import { readConfigFile } from '../functional_test_runner/lib'; -const makeSuccessMessage = options => { +const makeSuccessMessage = (options) => { const installDirFlag = options.installDir ? ` --kibana-install-dir=${options.installDir}` : ''; return ( @@ -92,7 +92,7 @@ export async function runTests(options) { continue; } - await withProcRunner(log, async procs => { + await withProcRunner(log, async (procs) => { const config = await readConfigFile(log, configPath); let es; @@ -128,7 +128,7 @@ export async function startServers(options) { log, }; - await withProcRunner(log, async procs => { + await withProcRunner(log, async (procs) => { const config = await readConfigFile(log, options.config); const es = await runElasticsearch({ config, options: opts }); diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 57cdc8ffd494f3..585ce8181df5f4 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -42,10 +42,8 @@ export { kbnTestConfig, kibanaServerTestUser, kibanaTestUser, adminTestUser } fr // @ts-ignore not typed yet export { setupUsers, DEFAULT_SUPERUSER_PASS } from './functional_tests/lib/auth'; -// @ts-ignore not typed yet export { readConfigFile } from './functional_test_runner/lib/config/read_config_file'; -// @ts-ignore not typed yet export { runFtrCli } from './functional_test_runner/cli'; export { diff --git a/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js index 6edd0a551ebd08..00a11432dd9e81 100644 --- a/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js +++ b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js @@ -49,8 +49,8 @@ describe('dev/mocha/junit report generation', () => { }); mocha.addFile(resolve(PROJECT_DIR, 'test.js')); - await new Promise(resolve => mocha.run(resolve)); - const report = await fcb(cb => + await new Promise((resolve) => mocha.run(resolve)); + const report = await fcb((cb) => parseString(readFileSync(makeJunitReportPath(PROJECT_DIR, 'test')), cb) ); diff --git a/packages/kbn-test/src/mocha/junit_report_generation.js b/packages/kbn-test/src/mocha/junit_report_generation.js index b56741b48d3670..7e39c32ee4db83 100644 --- a/packages/kbn-test/src/mocha/junit_report_generation.js +++ b/packages/kbn-test/src/mocha/junit_report_generation.js @@ -39,26 +39,26 @@ export function setupJUnitReportGeneration(runner, options = {}) { const stats = {}; const results = []; - const getDuration = node => + const getDuration = (node) => node.startTime && node.endTime ? ((node.endTime - node.startTime) / 1000).toFixed(3) : null; - const findAllTests = suite => + const findAllTests = (suite) => suite.suites.reduce((acc, suite) => acc.concat(findAllTests(suite)), suite.tests); - const setStartTime = node => { + const setStartTime = (node) => { node.startTime = dateNow(); }; - const setEndTime = node => { + const setEndTime = (node) => { node.endTime = dateNow(); }; - const getFullTitle = node => { + const getFullTitle = (node) => { const parentTitle = node.parent && getFullTitle(node.parent); return parentTitle ? `${parentTitle} ${node.title}` : node.title; }; - const getPath = node => { + const getPath = (node) => { if (node.file) { return relative(rootDirectory, node.file); } @@ -75,7 +75,7 @@ export function setupJUnitReportGeneration(runner, options = {}) { runner.on('hook', setStartTime); runner.on('hook end', setEndTime); runner.on('test', setStartTime); - runner.on('pass', node => results.push({ node })); + runner.on('pass', (node) => results.push({ node })); runner.on('pass', setEndTime); runner.on('fail', (node, error) => results.push({ failed: true, error, node })); runner.on('fail', setEndTime); @@ -89,16 +89,16 @@ export function setupJUnitReportGeneration(runner, options = {}) { } // filter out just the failures - const failures = results.filter(result => result.failed); + const failures = results.filter((result) => result.failed); // any failure that isn't for a test is for a hook - const failedHooks = failures.filter(result => !allTests.includes(result.node)); + const failedHooks = failures.filter((result) => !allTests.includes(result.node)); // mocha doesn't emit 'pass' or 'fail' when it skips a test // or a test is pending, so we find them ourselves const skippedResults = allTests - .filter(node => node.pending || !results.find(result => result.node === node)) - .map(node => ({ skipped: true, node })); + .filter((node) => node.pending || !results.find((result) => result.node === node)) + .map((node) => ({ skipped: true, node })); const builder = xmlBuilder.create( 'testsuites', @@ -124,7 +124,7 @@ export function setupJUnitReportGeneration(runner, options = {}) { }); } - [...results, ...skippedResults].forEach(result => { + [...results, ...skippedResults].forEach((result) => { const el = addTestcaseEl(result.node); if (result.failed) { diff --git a/packages/kbn-test/src/mocha/run_mocha_cli.js b/packages/kbn-test/src/mocha/run_mocha_cli.js index 77f40aded1d7fa..3c77fef963a76d 100644 --- a/packages/kbn-test/src/mocha/run_mocha_cli.js +++ b/packages/kbn-test/src/mocha/run_mocha_cli.js @@ -85,7 +85,7 @@ export function runMochaCli() { ], } ) - .forEach(file => { + .forEach((file) => { process.argv.push(file); }); } diff --git a/packages/kbn-ui-framework/Gruntfile.js b/packages/kbn-ui-framework/Gruntfile.js index cf0c1643055eb6..177fd1f153155c 100644 --- a/packages/kbn-ui-framework/Gruntfile.js +++ b/packages/kbn-ui-framework/Gruntfile.js @@ -26,7 +26,7 @@ const debounce = require('lodash/function/debounce'); const platform = require('os').platform(); const isPlatformWindows = /^win/.test(platform); -module.exports = function(grunt) { +module.exports = function (grunt) { grunt.initConfig({ clean: { target: ['target'], @@ -62,7 +62,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-copy'); grunt.registerTask('prodBuild', ['clean:target', 'copy:makeProdBuild', 'babel:prodBuild']); - grunt.registerTask('docSiteBuild', function() { + grunt.registerTask('docSiteBuild', function () { const done = this.async(); const serverCmd = { @@ -94,17 +94,17 @@ module.exports = function(grunt) { uiFrameworkServerBuild.then(done); }); - grunt.registerTask('docSiteStart', function() { + grunt.registerTask('docSiteStart', function () { const done = this.async(); Promise.all([uiFrameworkWatch(), uiFrameworkServerStart()]).then(done); }); - grunt.registerTask('compileCssLight', function() { + grunt.registerTask('compileCssLight', function () { const done = this.async(); uiFrameworkCompileLight().then(done); }); - grunt.registerTask('compileCssDark', function() { + grunt.registerTask('compileCssDark', function () { const done = this.async(); uiFrameworkCompileDark().then(done); }); @@ -146,19 +146,19 @@ module.exports = function(grunt) { const src = 'src/kui_light.scss'; const dest = 'dist/kui_light.css'; - return new Promise(resolve => { + return new Promise((resolve) => { sass.render( { file: src, }, - function(error, result) { + function (error, result) { if (error) { grunt.log.error(error); } postcss([postcssConfig]) .process(result.css, { from: src, to: dest }) - .then(result => { + .then((result) => { grunt.file.write(dest, result.css); if (result.map) { @@ -176,19 +176,19 @@ module.exports = function(grunt) { const src = 'src/kui_dark.scss'; const dest = 'dist/kui_dark.css'; - return new Promise(resolve => { + return new Promise((resolve) => { sass.render( { file: src, }, - function(error, result) { + function (error, result) { if (error) { grunt.log.error(error); } postcss([postcssConfig]) .process(result.css, { from: src, to: dest }) - .then(result => { + .then((result) => { grunt.file.write(dest, result.css); if (result.map) { diff --git a/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js b/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js index 205be7920aa60e..1836d00af4ab38 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js @@ -25,7 +25,7 @@ export const registerSection = (id, name) => ({ name, }); -export const unregisterSection = id => ({ +export const unregisterSection = (id) => ({ type: ActionTypes.UNREGISTER_SECTION, id, }); diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js b/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js index f5845becbe77f3..41aeb74d24b6b0 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js @@ -19,4 +19,4 @@ import React from 'react'; -export const GuideCode = props => {props.children}; +export const GuideCode = (props) => {props.children}; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js b/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js index b1d2f8e031f7c5..b387a89b7072cc 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js @@ -65,7 +65,7 @@ export class GuideCodeViewer extends Component { 'is-code-viewer-open': this.props.isOpen, }); - const codeSections = this.props.source.map(sourceObject => + const codeSections = this.props.source.map((sourceObject) => this.renderSection(sourceObject.type, sourceObject.code) ); diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js b/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js index 93470ac6de1280..d968e014370f88 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js @@ -68,7 +68,7 @@ export class GuideDemo extends Component { }); return ( -
(this.content = c)} {...rest}> +
(this.content = c)} {...rest}> {children}
); diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js b/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js index b49880e0e3bfa9..62d1e3ac8bedd3 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js @@ -19,7 +19,7 @@ import React from 'react'; -export const GuideLink = props => ( +export const GuideLink = (props) => ( {props.children} diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js b/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js index f31a3b10eef4ec..49225c96ba5e59 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js @@ -120,7 +120,7 @@ export class GuideNav extends Component { }); const componentNavItems = this.props.components - .filter(item => item.name.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1) + .filter((item) => item.name.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1) .map((item, index) => { const icon = item.hasReact ?
: undefined; return ( @@ -135,7 +135,7 @@ export class GuideNav extends Component { }); const sandboxNavItems = this.props.sandboxes - .filter(item => item.name.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1) + .filter((item) => item.name.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1) .map((item, index) => { const icon = item.hasReact ?
: undefined; return ( diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js index 5d8e6993abe4e8..0a7442fce47239 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js @@ -21,7 +21,7 @@ import { connect } from 'react-redux'; import { getSections } from '../../store'; import { GuidePage } from './guide_page'; -const mapStateToProps = state => ({ +const mapStateToProps = (state) => ({ sections: getSections(state), }); diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js index bd7dc0705c6d96..9aeca1b30e03da 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js @@ -20,7 +20,7 @@ import PropTypes from 'prop-types'; import React from 'react'; -export const GuidePageSideNav = props => { +export const GuidePageSideNav = (props) => { return (
{props.title}
diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js b/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js index 26c68dfe87951a..820e4728da86db 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js @@ -19,4 +19,4 @@ import React from 'react'; -export const GuideText = props =>
{props.children}
; +export const GuideText = (props) =>
{props.children}
; diff --git a/packages/kbn-ui-framework/doc_site/src/index.js b/packages/kbn-ui-framework/doc_site/src/index.js index 5473024ae93c9f..f7f1df059a0416 100644 --- a/packages/kbn-ui-framework/doc_site/src/index.js +++ b/packages/kbn-ui-framework/doc_site/src/index.js @@ -58,16 +58,16 @@ const routes = [ ]; // Update document title with route name. -const onRouteEnter = route => { +const onRouteEnter = (route) => { const leafRoute = route.routes[route.routes.length - 1]; document.title = leafRoute.name ? `Kibana UI Framework - ${leafRoute.name}` : 'Kibana UI Framework'; }; -const syncTitleWithRoutes = routesList => { +const syncTitleWithRoutes = (routesList) => { if (!routesList) return; - routesList.forEach(route => { + routesList.forEach((route) => { route.onEnter = onRouteEnter; // eslint-disable-line no-param-reassign if (route.indexRoute) { // Index routes have a weird relationship with their "parent" routes, diff --git a/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js b/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js index 32912d5eb9c86f..510a7fea7a0266 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js +++ b/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js @@ -159,14 +159,14 @@ export default { return allRoutes; }, getPreviousRoute: function getPreviousRoute(routeName) { - const index = allRoutes.findIndex(item => { + const index = allRoutes.findIndex((item) => { return item.name === routeName; }); return index >= 0 ? allRoutes[index - 1] : undefined; }, getNextRoute: function getNextRoute(routeName) { - const index = allRoutes.findIndex(item => { + const index = allRoutes.findIndex((item) => { return item.name === routeName; }); diff --git a/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js b/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js index f016857ff44142..2e0678f5697740 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js +++ b/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js @@ -32,7 +32,7 @@ function one(str) { } function each(items, src, dest) { - return items.map(item => { + return items.map((item) => { const _item = item; _item[dest] = one(_item[src]); return _item; diff --git a/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js b/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js index 6b61c009c51862..a86580903de686 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js +++ b/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js @@ -40,7 +40,7 @@ export default function sectionsReducer(state = defaultState, action) { case ActionTypes.UNREGISTER_SECTION: { const sections = state.sections.slice(); - const index = sections.findIndex(section => section.id === action.id); + const index = sections.findIndex((section) => section.id === action.id); sections.splice(index, 1); return { diff --git a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js index a71b2ff28ee655..9f2f1dec560550 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js @@ -36,7 +36,7 @@ import BarThreeSections from './bar_three_sections'; import barThreeSectionsSource from '!!raw-loader!./bar_three_sections'; const barThreeSectionsHtml = renderToHtml(BarThreeSections); -export default props => ( +export default (props) => ( (
{ + onSubmit={(e) => { e.preventDefault(); window.alert('Submit'); }} @@ -40,7 +40,7 @@ export default () => (
{ + onSubmit={(e) => { e.preventDefault(); window.alert('Submit'); }} diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js index daea2978aeffb5..4943748ab1830c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js @@ -71,7 +71,7 @@ const elementsHtml = renderToHtml(Elements); import sizesHtml from './button_sizes.html'; -export default props => ( +export default (props) => ( { + onToggleContent = (ev) => { ev.preventDefault(); - this.setState(state => ({ + this.setState((state) => ({ isExpanded: !state.isExpanded, })); }; diff --git a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js index d008a0d5f23f7a..52e8a91b17aa96 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js @@ -32,7 +32,7 @@ import CollapseButtonAria from './collapse_button_aria'; import collapseButtonAriaSource from '!!raw-loader!./collapse_button_aria'; const collapseButtonAriaHtml = renderToHtml(CollapseButtonAria); -export default props => ( +export default (props) => ( ( +export default (props) => ( this.handleChange(event, 'value1')} + onChange={(event) => this.handleChange(event, 'value1')} />
this.handleChange(event, 'value2')} + onChange={(event) => this.handleChange(event, 'value2')} />
this.handleChange(event, 'value3')} + onChange={(event) => this.handleChange(event, 'value3')} isDisabled />
this.handleChange(event, 'value4')} + onChange={(event) => this.handleChange(event, 'value4')} />
); diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js b/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js index 07174591515849..88edfc5242564d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js @@ -59,7 +59,7 @@ import CheckBox from './check_box'; import checkBoxSource from '!!raw-loader!./check_box'; const checkBoxHtml = renderToHtml(CheckBox); -export default props => ( +export default (props) => ( - this.handleChange(event, 'value1')}> + this.handleChange(event, 'value1')} + > @@ -44,7 +47,7 @@ class KuiSelectExample extends Component {
this.handleChange(event, 'value2')} + onChange={(event) => this.handleChange(event, 'value2')} isDisabled > @@ -52,7 +55,7 @@ class KuiSelectExample extends Component {
this.handleChange(event, 'value3')} + onChange={(event) => this.handleChange(event, 'value3')} isInvalid > @@ -60,7 +63,7 @@ class KuiSelectExample extends Component {
this.handleChange(event, 'value4')} + onChange={(event) => this.handleChange(event, 'value4')} size="small" > @@ -68,7 +71,7 @@ class KuiSelectExample extends Component {
this.handleChange(event, 'value5')} + onChange={(event) => this.handleChange(event, 'value5')} size="large" > diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js index b56051071a6da9..0d4e876d996a2f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js @@ -40,38 +40,38 @@ class KuiTextAreaExample extends Component { this.handleChange(event, 'value1')} + onChange={(event) => this.handleChange(event, 'value1')} />
this.handleChange(event, 'value2')} + onChange={(event) => this.handleChange(event, 'value2')} />
this.handleChange(event, 'value3')} + onChange={(event) => this.handleChange(event, 'value3')} />
this.handleChange(event, 'value4')} + onChange={(event) => this.handleChange(event, 'value4')} />
this.handleChange(event, 'value5')} + onChange={(event) => this.handleChange(event, 'value5')} />
this.handleChange(event, 'value6')} + onChange={(event) => this.handleChange(event, 'value6')} />
); diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js index aba16bae1269b2..65c7fa765a3593 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js @@ -33,7 +33,7 @@ class KuiTextAreaNonResizableExample extends Component { return ( this.handleChange(event, 'value1')} + onChange={(event) => this.handleChange(event, 'value1')} isNonResizable /> ); diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js index a3cebcb07bf2b1..5bb3fabe22fa5e 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js @@ -40,39 +40,39 @@ class KuiTextInputExample extends Component { this.handleChange(event, 'value1')} + onChange={(event) => this.handleChange(event, 'value1')} />
this.handleChange(event, 'value2')} + onChange={(event) => this.handleChange(event, 'value2')} />
this.handleChange(event, 'value3')} + onChange={(event) => this.handleChange(event, 'value3')} />
this.handleChange(event, 'value4')} + onChange={(event) => this.handleChange(event, 'value4')} />
this.handleChange(event, 'value5')} + onChange={(event) => this.handleChange(event, 'value5')} />
this.handleChange(event, 'value6')} + onChange={(event) => this.handleChange(event, 'value6')} />
); diff --git a/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js b/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js index 9c76a8b3a1d3a6..7b1a5d2785cac2 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js @@ -28,7 +28,7 @@ import FieldGroup from './field_group'; import fieldGroupSource from '!!raw-loader!./field_group'; const fieldGroupHtml = renderToHtml(FieldGroup); -export default props => ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( item.title.toLowerCase(), + getValue: (item) => item.title.toLowerCase(), isAscending: true, }, { name: 'description', - getValue: item => item.description.toLowerCase(), + getValue: (item) => item.description.toLowerCase(), isAscending: true, }, ], @@ -70,7 +70,7 @@ export class FluidTable extends Component { ); } - onSort = prop => { + onSort = (prop) => { this.sortableProperties.sortOn(prop); this.setState({ @@ -79,7 +79,7 @@ export class FluidTable extends Component { }; renderRows() { - return this.items.map(item => ( + return this.items.map((item) => ( {item.title} diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js index fece33c16980a3..38eaa7b396ef5d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js @@ -137,7 +137,7 @@ export class ListingTable extends Component { ]; } - onItemSelectionChanged = selectedRowIds => { + onItemSelectionChanged = (selectedRowIds) => { this.setState({ selectedRowIds }); }; diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/table.js b/packages/kbn-ui-framework/doc_site/src/views/table/table.js index 45f6e389e7234a..0c55d1dc5ed51f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/table.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/table.js @@ -85,12 +85,12 @@ export class Table extends Component { [ { name: 'title', - getValue: item => item.title.toLowerCase(), + getValue: (item) => item.title.toLowerCase(), isAscending: true, }, { name: 'status', - getValue: item => item.status.toLowerCase(), + getValue: (item) => item.status.toLowerCase(), isAscending: true, }, ], @@ -98,7 +98,7 @@ export class Table extends Component { ); } - onSort = prop => { + onSort = (prop) => { this.sortableProperties.sortOn(prop); this.setState({ @@ -106,35 +106,35 @@ export class Table extends Component { }); }; - toggleItem = item => { - this.setState(previousState => { + toggleItem = (item) => { + this.setState((previousState) => { const rowToSelectedStateMap = new Map(previousState.rowToSelectedStateMap); rowToSelectedStateMap.set(item, !rowToSelectedStateMap.get(item)); return { rowToSelectedStateMap }; }); }; - isItemChecked = item => { + isItemChecked = (item) => { return this.state.rowToSelectedStateMap.get(item); }; - togglePopover = item => { - this.setState(previousState => { + togglePopover = (item) => { + this.setState((previousState) => { const rowToOpenActionsPopoverMap = new Map(previousState.rowToOpenActionsPopoverMap); rowToOpenActionsPopoverMap.set(item, !rowToOpenActionsPopoverMap.get(item)); return { rowToOpenActionsPopoverMap }; }); }; - closePopover = item => { - this.setState(previousState => { + closePopover = (item) => { + this.setState((previousState) => { const rowToOpenActionsPopoverMap = new Map(previousState.rowToOpenActionsPopoverMap); rowToOpenActionsPopoverMap.set(item, false); return { rowToOpenActionsPopoverMap }; }); }; - isPopoverOpen = item => { + isPopoverOpen = (item) => { return this.state.rowToOpenActionsPopoverMap.get(item); }; @@ -146,7 +146,7 @@ export class Table extends Component { renderRows() { const rows = []; - this.items.forEach(item => { + this.items.forEach((item) => { const classes = classNames({ 'kuiTableRowCell--wrap': item.isWrapped, }); diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js b/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js index 9ed449ea9767bd..07e328c4e5e839 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js @@ -52,7 +52,7 @@ import { ListingTableLoadingItems } from './listing_table_loading_items'; import listingTableLoadingItemsSource from '!!raw-loader!./listing_table_loading_items'; // eslint-disable-line import/default const listingTableLoadingItemsHtml = renderToHtml(ListingTableLoadingItems); -export default props => ( +export default (props) => ( { + onSelectedTabChanged = (id) => { this.setState({ selectedTabId: id, }); diff --git a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js index 0d3663167520ed..125fd0fb53ae31 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js @@ -35,7 +35,7 @@ import Tabs from './tabs'; import tabsSource from '!!raw-loader!./tabs'; const tabsHtml = renderToHtml(Tabs); -export default props => ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( ( +export default (props) => ( diff --git a/packages/kbn-ui-framework/generator-kui/app/component.js b/packages/kbn-ui-framework/generator-kui/app/component.js index 1cf03b89d54f7e..bcb561f6fa7295 100644 --- a/packages/kbn-ui-framework/generator-kui/app/component.js +++ b/packages/kbn-ui-framework/generator-kui/app/component.js @@ -39,7 +39,7 @@ module.exports = class extends Generator { }, ], }, - ]).then(answers => { + ]).then((answers) => { this.config = answers; }); } diff --git a/packages/kbn-ui-framework/generator-kui/app/documentation.js b/packages/kbn-ui-framework/generator-kui/app/documentation.js index c2735f1ce978b0..3cbc0263789c65 100644 --- a/packages/kbn-ui-framework/generator-kui/app/documentation.js +++ b/packages/kbn-ui-framework/generator-kui/app/documentation.js @@ -43,7 +43,7 @@ module.exports = class extends Generator { }, ], }, - ]).then(answers => { + ]).then((answers) => { this.config = answers; }); } diff --git a/packages/kbn-ui-framework/generator-kui/component/index.js b/packages/kbn-ui-framework/generator-kui/component/index.js index 3abf84b7a2073a..56c49fe6fa4717 100644 --- a/packages/kbn-ui-framework/generator-kui/component/index.js +++ b/packages/kbn-ui-framework/generator-kui/component/index.js @@ -49,7 +49,7 @@ module.exports = class extends Generator { type: 'confirm', default: true, }, - ]).then(answers => { + ]).then((answers) => { this.config = answers; if (!answers.name || !answers.name.trim()) { @@ -62,7 +62,7 @@ module.exports = class extends Generator { writing() { const config = this.config; - const writeComponent = isStatelessFunction => { + const writeComponent = (isStatelessFunction) => { const componentName = utils.makeComponentName(config.name); const cssClassName = utils.lowerCaseFirstLetter(componentName); const fileName = config.name; diff --git a/packages/kbn-ui-framework/generator-kui/documentation/index.js b/packages/kbn-ui-framework/generator-kui/documentation/index.js index daaaf32c8fd22a..03f8d5813b2515 100644 --- a/packages/kbn-ui-framework/generator-kui/documentation/index.js +++ b/packages/kbn-ui-framework/generator-kui/documentation/index.js @@ -47,7 +47,7 @@ module.exports = class extends Generator { name: 'folderName', type: 'input', store: true, - default: answers => answers.name, + default: (answers) => answers.name, }); prompts.push({ @@ -58,7 +58,7 @@ module.exports = class extends Generator { }); } - return this.prompt(prompts).then(answers => { + return this.prompt(prompts).then((answers) => { this.config = answers; }); } diff --git a/packages/kbn-ui-framework/generator-kui/utils.js b/packages/kbn-ui-framework/generator-kui/utils.js index c51393121777e4..0f7b910451767e 100644 --- a/packages/kbn-ui-framework/generator-kui/utils.js +++ b/packages/kbn-ui-framework/generator-kui/utils.js @@ -21,7 +21,7 @@ function makeComponentName(str, usePrefix = true) { const words = str.split('_'); const componentName = words - .map(function(word) { + .map(function (word) { return upperCaseFirstLetter(word); }) .join(''); @@ -30,13 +30,13 @@ function makeComponentName(str, usePrefix = true) { } function lowerCaseFirstLetter(str) { - return str.replace(/\w\S*/g, function(txt) { + return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toLowerCase() + txt.substr(1); }); } function upperCaseFirstLetter(str) { - return str.replace(/\w\S*/g, function(txt) { + return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1); }); } diff --git a/packages/kbn-ui-framework/src/components/button/button.js b/packages/kbn-ui-framework/src/components/button/button.js index b18ca87a27b1e7..e95b9209343ae2 100644 --- a/packages/kbn-ui-framework/src/components/button/button.js +++ b/packages/kbn-ui-framework/src/components/button/button.js @@ -133,7 +133,7 @@ const KuiLinkButton = ({ children, ...rest }) => { - const onClick = e => { + const onClick = (e) => { if (disabled) { e.preventDefault(); } diff --git a/packages/kbn-ui-framework/src/components/button/button.test.js b/packages/kbn-ui-framework/src/components/button/button.test.js index d664ce85f9a377..db74308d9de8de 100644 --- a/packages/kbn-ui-framework/src/components/button/button.test.js +++ b/packages/kbn-ui-framework/src/components/button/button.test.js @@ -48,7 +48,7 @@ describe('KuiButton', () => { describe('Props', () => { describe('buttonType', () => { - BUTTON_TYPES.forEach(buttonType => { + BUTTON_TYPES.forEach((buttonType) => { describe(`${buttonType}`, () => { test(`renders the ${buttonType} class`, () => { const $button = render(); diff --git a/packages/kbn-ui-framework/src/components/button/button_group/button_group.js b/packages/kbn-ui-framework/src/components/button/button_group/button_group.js index 49eaff03efd402..630d5598cab9cf 100644 --- a/packages/kbn-ui-framework/src/components/button/button_group/button_group.js +++ b/packages/kbn-ui-framework/src/components/button/button_group/button_group.js @@ -22,7 +22,7 @@ import React from 'react'; import classNames from 'classnames'; -const KuiButtonGroup = props => { +const KuiButtonGroup = (props) => { const classes = classNames('kuiButtonGroup', { 'kuiButtonGroup--united': props.isUnited, }); diff --git a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js index 736e349396b7e8..256d7c4a1786e2 100644 --- a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js +++ b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js @@ -24,7 +24,7 @@ import classNames from 'classnames'; const ICON_TYPES = ['create', 'delete', 'previous', 'next', 'loading', 'settings', 'menu']; -const KuiButtonIcon = props => { +const KuiButtonIcon = (props) => { const typeToClassNameMap = { create: 'fa-plus', delete: 'fa-trash', diff --git a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js index e270f266443930..553fef1432487c 100644 --- a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js +++ b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js @@ -33,7 +33,7 @@ describe('KuiButtonIcon', () => { describe('Props', () => { describe('type', () => { - ICON_TYPES.forEach(type => { + ICON_TYPES.forEach((type) => { describe(`${type}`, () => { test(`renders the ${type} class`, () => { const $buttonIcon = render(); diff --git a/packages/kbn-ui-framework/src/components/button/link_button.test.js b/packages/kbn-ui-framework/src/components/button/link_button.test.js index 4f77af3febf54a..4489dc1a46d2aa 100644 --- a/packages/kbn-ui-framework/src/components/button/link_button.test.js +++ b/packages/kbn-ui-framework/src/components/button/link_button.test.js @@ -49,7 +49,7 @@ describe('KuiLinkButton', () => { describe('Props', () => { describe('buttonType', () => { - BUTTON_TYPES.forEach(buttonType => { + BUTTON_TYPES.forEach((buttonType) => { describe(`${buttonType}`, () => { test(`renders the ${buttonType} class`, () => { const $button = render( diff --git a/packages/kbn-ui-framework/src/components/button/submit_button.test.js b/packages/kbn-ui-framework/src/components/button/submit_button.test.js index fc30523649c128..77ad9eb40c55fd 100644 --- a/packages/kbn-ui-framework/src/components/button/submit_button.test.js +++ b/packages/kbn-ui-framework/src/components/button/submit_button.test.js @@ -47,7 +47,7 @@ describe('KuiSubmitButton', () => { describe('Props', () => { describe('buttonType', () => { - BUTTON_TYPES.forEach(buttonType => { + BUTTON_TYPES.forEach((buttonType) => { describe(`${buttonType}`, () => { test(`renders the ${buttonType} class`, () => { const $button = render(); diff --git a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js index f6245ef654bb9a..8ce225038b8b79 100644 --- a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js +++ b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js @@ -27,7 +27,7 @@ import { DIRECTIONS, KuiCollapseButton } from './collapse_button'; describe('KuiCollapseButton', () => { describe('Props', () => { describe('direction', () => { - DIRECTIONS.forEach(direction => { + DIRECTIONS.forEach((direction) => { describe(`${direction}`, () => { test(`renders the ${direction} class`, () => { const component = ; diff --git a/packages/kbn-ui-framework/src/components/form/select/select.test.js b/packages/kbn-ui-framework/src/components/form/select/select.test.js index 81c1e4d9a0ff2d..056bc88016d51a 100644 --- a/packages/kbn-ui-framework/src/components/form/select/select.test.js +++ b/packages/kbn-ui-framework/src/components/form/select/select.test.js @@ -77,7 +77,7 @@ describe('KuiSelect', () => { }); describe('size', () => { - SELECT_SIZE.forEach(size => { + SELECT_SIZE.forEach((size) => { test(`renders ${size}`, () => { const component = {}} />; diff --git a/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js b/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js index eddb655094088b..d87b7b76789de8 100644 --- a/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js +++ b/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js @@ -87,7 +87,7 @@ describe('KuiTextArea', () => { }); describe('size', () => { - TEXTAREA_SIZE.forEach(size => { + TEXTAREA_SIZE.forEach((size) => { test(`renders ${size}`, () => { const component = {}} />; diff --git a/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js b/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js index 9ef3c420bba68d..41d3726582fb57 100644 --- a/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js +++ b/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js @@ -89,7 +89,7 @@ describe('KuiTextInput', () => { }); describe('size', () => { - TEXTINPUT_SIZE.forEach(size => { + TEXTINPUT_SIZE.forEach((size) => { test(`renders ${size}`, () => { const component = {}} />; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js index 3478c159cbbb9b..82b2afba7bc40a 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js @@ -57,7 +57,7 @@ export function KuiListingTable({ if (areAllRowsSelected()) { onItemSelectionChanged([]); } else { - onItemSelectionChanged(rows.map(row => row.id)); + onItemSelectionChanged(rows.map((row) => row.id)); } } diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js index b47a1275d15655..2607caeba0dbbf 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js @@ -22,7 +22,7 @@ import { mount, shallow } from 'enzyme'; import { requiredProps, takeMountedSnapshot } from '../../../test'; import { KuiListingTable } from './listing_table'; -const getProps = customProps => { +const getProps = (customProps) => { const defaultProps = { header: ['Breed', 'Description'], rows: [ @@ -59,20 +59,14 @@ test('renders KuiListingTable', () => { test('selecting a row calls onItemSelectionChanged', () => { const props = getProps(); const component = shallow(); - component - .find('KuiListingTableRow') - .at(1) - .prop('onSelectionChanged')('1'); + component.find('KuiListingTableRow').at(1).prop('onSelectionChanged')('1'); expect(props.onItemSelectionChanged).toHaveBeenCalledWith(['1']); }); test('selectedRowIds is preserved when onItemSelectionChanged is called', () => { const props = getProps({ selectedRowIds: ['3'] }); const component = shallow(); - component - .find('KuiListingTableRow') - .at(0) - .prop('onSelectionChanged')('1'); + component.find('KuiListingTableRow').at(0).prop('onSelectionChanged')('1'); expect(props.onItemSelectionChanged).toHaveBeenCalledWith(expect.arrayContaining(['1', '3'])); }); diff --git a/packages/kbn-ui-framework/src/components/typography/typography.test.js b/packages/kbn-ui-framework/src/components/typography/typography.test.js index 7155483354e48e..b341a2c442fb2d 100644 --- a/packages/kbn-ui-framework/src/components/typography/typography.test.js +++ b/packages/kbn-ui-framework/src/components/typography/typography.test.js @@ -35,7 +35,7 @@ describe('KuiTitle', () => { }); describe('renders size', () => { - SIZES.forEach(size => { + SIZES.forEach((size) => { test(size, () => { const component = render( diff --git a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js index 6537f0d157997d..164910341f027b 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js +++ b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js @@ -27,5 +27,5 @@ import uuid from 'uuid'; */ export function htmlIdGenerator(idPrefix) { const prefix = idPrefix || uuid.v1(); - return suffix => `${prefix}_${suffix || uuid.v1()}`; + return (suffix) => `${prefix}_${suffix || uuid.v1()}`; } diff --git a/packages/kbn-ui-framework/src/services/sort/sortable_properties.js b/packages/kbn-ui-framework/src/services/sort/sortable_properties.js index 4b08b20b68cbf4..6c445bf8b747be 100644 --- a/packages/kbn-ui-framework/src/services/sort/sortable_properties.js +++ b/packages/kbn-ui-framework/src/services/sort/sortable_properties.js @@ -73,7 +73,7 @@ export class SortableProperties { * @returns {SortableProperty|undefined} */ getSortablePropertyByName(propertyName) { - return this.sortableProperties.find(property => property.name === propertyName); + return this.sortableProperties.find((property) => property.name === propertyName); } /** diff --git a/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js b/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js index 223724edac8b88..0037787830ac2d 100644 --- a/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js +++ b/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js @@ -22,19 +22,19 @@ import { SortableProperties } from './sortable_properties'; describe('SortProperties', () => { const name = { name: 'name', - getValue: bird => bird.name, + getValue: (bird) => bird.name, isAscending: true, }; const size = { name: 'size', - getValue: bird => bird.size, + getValue: (bird) => bird.size, isAscending: false, }; const color = { name: 'color', - getValue: bird => bird.color, + getValue: (bird) => bird.color, isAscending: true, }; diff --git a/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js b/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js index 4d87930d434b5f..d4567ebb800fe7 100644 --- a/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js +++ b/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js @@ -23,7 +23,7 @@ * containing both React components and HTML elements. This function removes the React components, * leaving only HTML elements in the snapshot. */ -export const takeMountedSnapshot = mountedComponent => { +export const takeMountedSnapshot = (mountedComponent) => { const html = mountedComponent.html(); const template = document.createElement('template'); template.innerHTML = html; // eslint-disable-line no-unsanitized/property diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index f19271de8ad278..26efd174f4e39a 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -48,9 +48,16 @@ export const ElasticCharts = require('@elastic/charts'); export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibServices = require('@elastic/eui/lib/services'); export const ElasticEuiLibServicesFormat = require('@elastic/eui/lib/services/format'); -export const ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_light.json'); -export const ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_dark.json'); export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme'); +export let ElasticEuiLightTheme; +export let ElasticEuiDarkTheme; +if (window.__kbnThemeVersion__ === 'v7') { + ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_light.json'); + ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_dark.json'); +} else { + ElasticEuiLightTheme = require('@elastic/eui/dist/eui_theme_amsterdam_light.json'); + ElasticEuiDarkTheme = require('@elastic/eui/dist/eui_theme_amsterdam_dark.json'); +} // massive deps that we should really get rid of or reduce in size substantially export const ElasticsearchBrowser = require('elasticsearch-browser/elasticsearch.js'); diff --git a/packages/kbn-ui-shared-deps/index.d.ts b/packages/kbn-ui-shared-deps/index.d.ts index b829c87d91c4ab..cd659b6f048535 100644 --- a/packages/kbn-ui-shared-deps/index.d.ts +++ b/packages/kbn-ui-shared-deps/index.d.ts @@ -42,11 +42,21 @@ export const baseCssDistFilename: string; */ export const darkCssDistFilename: string; +/** + * Filename of the dark-theme css file in the distributable directory + */ +export const darkV8CssDistFilename: string; + /** * Filename of the light-theme css file in the distributable directory */ export const lightCssDistFilename: string; +/** + * Filename of the light-theme css file in the distributable directory + */ +export const lightV8CssDistFilename: string; + /** * Externals mapping inteded to be used in a webpack config */ diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index 42ed08259ac8fd..9aec3ab3599242 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -23,8 +23,10 @@ exports.distDir = Path.resolve(__dirname, 'target'); exports.jsDepFilenames = ['kbn-ui-shared-deps.@elastic.js']; exports.jsFilename = 'kbn-ui-shared-deps.js'; exports.baseCssDistFilename = 'kbn-ui-shared-deps.css'; -exports.lightCssDistFilename = 'kbn-ui-shared-deps.light.css'; -exports.darkCssDistFilename = 'kbn-ui-shared-deps.dark.css'; +exports.lightCssDistFilename = 'kbn-ui-shared-deps.v7.light.css'; +exports.lightV8CssDistFilename = 'kbn-ui-shared-deps.v8.light.css'; +exports.darkCssDistFilename = 'kbn-ui-shared-deps.v7.dark.css'; +exports.darkV8CssDistFilename = 'kbn-ui-shared-deps.v8.dark.css'; exports.externals = { // stateful deps angular: '__kbnSharedDeps__.Angular', diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 8259f251a9be3b..d34fe3624ab266 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -6,11 +6,11 @@ "scripts": { "build": "node scripts/build", "kbn:bootstrap": "node scripts/build --dev", - "kbn:watch": "node scripts/build --watch" + "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { "@elastic/charts": "19.2.0", - "@elastic/eui": "22.3.1", + "@elastic/eui": "23.3.1", "@kbn/i18n": "1.0.0", "abortcontroller-polyfill": "^1.4.0", "angular": "^1.7.9", diff --git a/packages/kbn-ui-shared-deps/public_path_loader.js b/packages/kbn-ui-shared-deps/public_path_loader.js index 6b7a27c9ca52b6..fceebd6d6b3a1e 100644 --- a/packages/kbn-ui-shared-deps/public_path_loader.js +++ b/packages/kbn-ui-shared-deps/public_path_loader.js @@ -17,7 +17,7 @@ * under the License. */ -module.exports = function(source) { +module.exports = function (source) { const options = this.query; return `__webpack_public_path__ = window.__kbnPublicPath__['${options.key}'];${source}`; }; diff --git a/packages/kbn-ui-shared-deps/scripts/build.js b/packages/kbn-ui-shared-deps/scripts/build.js index e45b3dbed1748f..af4e3481e624d0 100644 --- a/packages/kbn-ui-shared-deps/scripts/build.js +++ b/packages/kbn-ui-shared-deps/scripts/build.js @@ -38,7 +38,7 @@ run( ); /** @param {webpack.Stats} stats */ - const onCompilationComplete = stats => { + const onCompilationComplete = (stats) => { const took = Math.round((stats.endTime - stats.startTime) / 1000); if (!stats.hasErrors() && !stats.hasWarnings()) { @@ -55,7 +55,7 @@ run( }; if (flags.watch) { - compiler.hooks.done.tap('report on stats', stats => { + compiler.hooks.done.tap('report on stats', (stats) => { try { onCompilationComplete(stats); } catch (error) { @@ -72,7 +72,7 @@ run( log.info('Running webpack compilation...'); }); - compiler.watch({}, error => { + compiler.watch({}, (error) => { if (error) { log.error('Fatal webpack error'); log.error(error); diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js index ca913d0f16417d..7295f2e88c530f 100644 --- a/packages/kbn-ui-shared-deps/webpack.config.js +++ b/packages/kbn-ui-shared-deps/webpack.config.js @@ -32,14 +32,22 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ mode: dev ? 'development' : 'production', entry: { 'kbn-ui-shared-deps': './entry.js', - 'kbn-ui-shared-deps.dark': [ + 'kbn-ui-shared-deps.v7.dark': [ '@elastic/eui/dist/eui_theme_dark.css', '@elastic/charts/dist/theme_only_dark.css', ], - 'kbn-ui-shared-deps.light': [ + 'kbn-ui-shared-deps.v7.light': [ '@elastic/eui/dist/eui_theme_light.css', '@elastic/charts/dist/theme_only_light.css', ], + 'kbn-ui-shared-deps.v8.dark': [ + '@elastic/eui/dist/eui_theme_amsterdam_dark.css', + '@elastic/charts/dist/theme_only_dark.css', + ], + 'kbn-ui-shared-deps.v8.light': [ + '@elastic/eui/dist/eui_theme_amsterdam_light.css', + '@elastic/charts/dist/theme_only_light.css', + ], }, context: __dirname, devtool: dev ? '#cheap-source-map' : false, @@ -47,7 +55,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ path: UiSharedDeps.distDir, filename: '[name].js', sourceMapFilename: '[file].map', - devtoolModuleFilenameTemplate: info => + devtoolModuleFilenameTemplate: (info) => `kbn-ui-shared-deps/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`, library: '__kbnSharedDeps__', }, @@ -96,7 +104,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ cacheGroups: { 'kbn-ui-shared-deps.@elastic': { name: 'kbn-ui-shared-deps.@elastic', - test: m => m.resource && m.resource.includes('@elastic'), + test: (m) => m.resource && m.resource.includes('@elastic'), chunks: 'all', enforce: true, }, diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 657d9f547de66e..9a8a81460f410e 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -82,9 +82,9 @@ export type Values = T extends any[] ? T[number] : T extends object ? T[keyof * type. This is necessary in the case of distinguishing one collection from * another. */ -export type UnionToIntersection = (U extends any -? (k: U) => void -: never) extends (k: infer I) => void +export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I +) => void ? I : never; diff --git a/renovate.json5 b/renovate.json5 index c4efa86366bf40..f5bb39a16fe465 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -426,6 +426,14 @@ '@types/indent-string', ], }, + { + groupSlug: 'inquirer', + groupName: 'inquirer related packages', + packageNames: [ + 'inquirer', + '@types/inquirer', + ], + }, { groupSlug: 'intl-relativeformat', groupName: 'intl-relativeformat related packages', @@ -683,6 +691,14 @@ '@types/node-forge', ], }, + { + groupSlug: 'node-sass', + groupName: 'node-sass related packages', + packageNames: [ + 'node-sass', + '@types/node-sass', + ], + }, { groupSlug: 'nodemailer', groupName: 'nodemailer related packages', @@ -951,6 +967,22 @@ '@types/tempy', ], }, + { + groupSlug: 'through2', + groupName: 'through2 related packages', + packageNames: [ + 'through2', + '@types/through2', + ], + }, + { + groupSlug: 'through2-map', + groupName: 'through2-map related packages', + packageNames: [ + 'through2-map', + '@types/through2-map', + ], + }, { groupSlug: 'tinycolor2', groupName: 'tinycolor2 related packages', @@ -1003,6 +1035,14 @@ ], enabled: false, }, + { + groupSlug: 'vinyl', + groupName: 'vinyl related packages', + packageNames: [ + 'vinyl', + '@types/vinyl', + ], + }, { groupSlug: 'vinyl-fs', groupName: 'vinyl-fs related packages', diff --git a/rfcs/text/0011_global_search.md b/rfcs/text/0011_global_search.md new file mode 100644 index 00000000000000..5ec368a1c2f022 --- /dev/null +++ b/rfcs/text/0011_global_search.md @@ -0,0 +1,591 @@ +- Start Date: 2020-04-19 +- RFC PR: [#64284](https://github.com/elastic/kibana/pull/64284) +- Kibana Issue: [#61657](https://github.com/elastic/kibana/issues/61657) + +# Summary + +A new Kibana plugin exposing an API on both public and server side, to allow consumers to search for various objects and +register result providers. + +Note: whether this will be an oss or xpack plugin still depends on https://github.com/elastic/dev/issues/1404. + +# Basic example + +- registering a result provider: + +```ts +setupDeps.globalSearch.registerResultProvider({ + id: 'my_provider', + find: (term, options, context) => { + const resultPromise = myService.search(term, context.core.savedObjects.client); + return from(resultPromise); + }, +}); +``` + +- using the `find` API from the client-side: + +```ts +startDeps.globalSearch.find('some term').subscribe( + ({ results }) => { + updateResults(results); + }, + () => {}, + () => { + showAsyncSearchIndicator(false); + } +); +``` + +# Motivation + +Kibana should do its best to assist users searching for and navigating to the various objects present on the Kibana platform. + +We should expose an API to make it possible for plugins to search for the various objects present on a Kibana instance. + +The first consumer of this API will be the global search bar [#57576](https://github.com/elastic/kibana/issues/57576). This API +should still be generic to answer similar needs from any other consumer, either client or server side. + +# Detailed design + +## API Design + +### Result provider API + +#### common types + +```ts +/** + * Static, non exhaustive list of the common search types. + * Only present to allow consumers and result providers to have aliases to the most common types. + */ +enum GlobalSearchCommonResultTypes { + application = 'application', + dashboard = 'dashboard', + visualization = 'visualization', + search = 'search', +} + +/** + * Options provided to {@link GlobalSearchResultProvider | result providers} `find` method. + */ +interface GlobalSearchProviderFindOptions { + /** + * A custom preference token associated with a search 'session' that should be used to get consistent scoring + * when performing calls to ES. Can also be used as a 'session' token for providers returning data from elsewhere + * than an elasticsearch cluster. + */ + preference: string; + /** + * Observable that emit once if and when the `find` call has been aborted by the consumer, or when the timeout period as been reached. + * When a `find` request is aborted, the service will stop emitting any new result to the consumer anyway, but + * this can (and should) be used to cancel any pending asynchronous task and complete the result observable. + */ + aborted$: Observable; + /** + * The total maximum number of results (including all batches / emissions) that should be returned by the provider for a given `find` request. + * Any result emitted exceeding this quota will be ignored by the service and not emitted to the consumer. + */ + maxResults: number; +} + +/** + * Representation of a result returned by a {@link GlobalSearchResultProvider | result provider} + */ +interface GlobalSearchProviderResult { + /** an id that should be unique for an individual provider's results */ + id: string; + /** the title/label of the result */ + title: string; + /** the type of result */ + type: string; + /** an optional EUI icon name to associate with the search result */ + icon?: string; + /** + * The url associated with this result. + * This can be either an absolute url, a path relative to the basePath, or a structure specifying if the basePath should be prepended. + * + * @example + * `result.url = 'https://kibana-instance:8080/base-path/app/my-app/my-result-type/id';` + * `result.url = '/app/my-app/my-result-type/id';` + * `result.url = { path: '/base-path/app/my-app/my-result-type/id', prependBasePath: false };` + */ + url: string | { path: string; prependBasePath: boolean }; + /** the score of the result, from 1 (lowest) to 100 (highest) */ + score: number; + /** an optional record of metadata for this result */ + meta?: Record; +} +``` + +Notes: + +- The `Serializable` type should be implemented and exposed from `core`. A basic implementation could be: + +```ts +type Serializable = string | number | boolean | PrimitiveArray | PrimitiveRecord; +interface PrimitiveArray extends Array {} +interface PrimitiveRecord extends Record {} +``` + +#### server + +```ts +/** + * Context passed to server-side {@GlobalSearchResultProvider | result provider}'s `find` method. + */ +export interface GlobalSearchProviderContext { + core: { + savedObjects: { + client: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + }; + elasticsearch: { + legacy: { + client: IScopedClusterClient; + }; + }; + uiSettings: { + client: IUiSettingsClient; + }; + }; +} + +/** + * GlobalSearch result provider, to be registered using the {@link GlobalSearchSetup | global search API} + */ +type GlobalSearchResultProvider = { + id: string; + find( + term: string, + options: GlobalSearchProviderFindOptions, + context: GlobalSearchProviderContext + ): Observable; +}; +``` + +Notes: + +- Initial implementation will only provide a static / non extensible `GlobalSearchProviderContext` context. + It would be possible to allow plugins to register their own context providers as it's done for `RequestHandlerContext`, + but this will not be done until the need arises. +- The performing `request` object could also be exposed on the context to allow result providers + to scope their custom services if needed. However as the previous option, this should only be done once needed. + +#### public + +```ts +/** + * GlobalSearch result provider, to be registered using the {@link GlobalSearchSetup | global search API} + */ +type GlobalSearchResultProvider = { + id: string; + find( + term: string, + options: GlobalSearchProviderFindOptions + ): Observable; +}; +``` + +Notes: + +- The client-side version of `GlobalSearchResultProvider` is slightly different than the + server one, as there is no `context` parameter on the `find` signature. + +### Plugin API + +#### server API + +```ts +/** + * Representation of a result returned by the {@link GlobalSearchPluginStart.find | `find` API} + */ +type GlobalSearchResult = Omit & { + /** + * The url associated with this result. + * This can be either an absolute url, or a relative path including the basePath + */ + url: string; +}; + +/** + * Options for the server-side {@link GlobalSearchServiceStart.find | find API} + */ +interface GlobalSearchFindOptions { + /** + * a custom preference token associated with a search 'session' that should be used to get consistent scoring + * when performing calls to ES. Can also be used as a 'session' token for providers returning data from elsewhere + * than an elasticsearch cluster. + * If not specified, a random token will be generated and used when callingn the underlying result providers. + */ + preference?: string; + /** + * Optional observable to notify that the associated `find` call should be canceled. + * If/when provided and emitting, the result observable will be completed and no further result emission will be performed. + */ + aborted$?: Observable; +} + +/** + * Response returned from the server-side {@link GlobalSearchServiceStart | global search service}'s `find` API + */ +type GlobalSearchBatchedResults = { + /** + * Results for this batch + */ + results: GlobalSearchResult[]; +}; + +/** @public */ +interface GlobalSearchPluginSetup { + registerResultProvider(provider: GlobalSearchResultProvider); +} + +/** @public */ +interface GlobalSearchPluginStart { + find( + term: string, + options: GlobalSearchFindOptions, + request: KibanaRequest + ): Observable; +} +``` + +#### public API + +```ts +/** + * Options for the client-side {@link GlobalSearchServiceStart.find | find API} + */ +interface GlobalSearchFindOptions { + /** + * Optional observable to notify that the associated `find` call should be canceled. + * If/when provided and emitting, the result observable will be completed and no further result emission will be performed. + */ + aborted$?: Observable; +} + +/** + * Enhanced {@link GlobalSearchResult | result type} for the client-side, + * to allow navigating to a given result. + */ +interface NavigableGlobalSearchResult extends GlobalSearchResult { + /** + * Navigate to this result's associated url. If the result is on this kibana instance, user will be redirected to it + * in a SPA friendly way using `application.navigateToApp`, else, a full page refresh will be performed. + */ + navigate: () => Promise; +} + +/** + * Response returned from the client-side {@link GlobalSearchServiceStart | global search service}'s `find` API + */ +type GlobalSearchBatchedResults = { + /** + * Results for this batch + */ + results: NavigableGlobalSearchResult[]; +}; + +/** @public */ +interface GlobalSearchPluginSetup { + registerResultProvider(provider: GlobalSearchResultProvider); +} + +/** @public */ +interface GlobalSearchPluginStart { + find(term: string, options: GlobalSearchFindOptions): Observable; +} +``` + +Notes: + +- The public API is very similar to its server counterpart. The differences are: + - The `registerResultProvider` setup APIs share the same signature, however the input `GlobalSearchResultProvider` + types are different on the client and server. + - The `find` start API signature got a `KibanaRequest` for `server`, when this parameter is not present for `public`. +- The `find` API returns a observable of `NavigableGlobalSearchResult` instead of plain `GlobalSearchResult`. This type + is here to enhance results with a `navigate` method to let the `GlobalSearch` plugin handle the navigation logic, which is + non-trivial. See the [Redirecting to a result](#redirecting-to-a-result) section for more info. + +#### http API + +An internal HTTP API will be exposed on `/internal/global_search/find` to allow the client-side `GlobalSearch` plugin +to fetch results from the server-side result providers. + +It should be very close to: + +```ts +router.post( + { + path: '/internal/global_search/find', + validate: { + body: schema.object({ + term: schema.string(), + options: schema.maybe( + schema.object({ + preference: schema.maybe(schema.string()), + }) + ), + }), + }, + }, + async (ctx, req, res) => { + const { term, options } = req.body; + const results = await ctx.globalSearch + .find(term, { ...options, $aborted: req.events.aborted$ }) + .pipe(reduce((acc, results) => [...acc, ...results])) + .toPromise(); + return res.ok({ + body: { + results, + }, + }); + } +); +``` + +Notes: + +- This API is only for internal use and communication between the client and the server parts of the `GS` API. When + the need to expose an API for external consumers will appear, a new public API will be exposed for that. +- A new `globalSearch` context will be exposed on core's `RequestHandlerContext` to wrap a `find` call with current request. +- Example implementation is awaiting for all results and then returns them as a single response. Ideally, we would + leverage the `bfetch` plugin to stream the results to the client instead. + +## Functional behavior + +### summary + +- the `GlobalSearch` plugin setup contract exposes an API to be able to register result providers (`GlobalSearchResultProvider`). + These providers can be registered from either public or server side, even if the interface for each side is not + exactly the same. +- the `GlobalSearch` plugin start contract exposes an API to be able to search for objects. This API is available from both public + and server sides. + - When using the server `find` API, only results from providers registered from the server will be returned. + - When using the public `find` API, results from provider registered from both server and public sides will be returned. +- During a `find` call, the service will call all the registered result providers and collect their result observables. + Every time a result provider emits some new results, the `globalSearch` service will: + - process them to convert their url to the expected output format + - emit the processed results + +### result provider registration + +Due to the fact that some kind of results (i.e `application`, and maybe later `management_section`) only exists on +the public side of Kibana and therefor are not known on the server side, the `registerResultProvider` API will be +available both from the public and the server counterpart of the `GlobalSearchPluginSetup` contract. + +However, as results from providers registered from the client-side will not be available from the server's `find` API, +registering result providers from the client should only be done to answer this specific use case and will be +discouraged, by providing appropriated jsdoc and documentation explaining that it should only +be used when it is not technically possible to register it from the server side instead. + +### results url processing + +When retrieving results from providers, the GS service will convert them from the provider's `GlobalSearchProviderResult` +result type to `GlobalSeachResult`, which is the structure returned from the `GlobalSearchPluginStart.find` observable. + +In current specification, the only conversion step is to transform the `result.url` property following this logic: + +- if `url` is an absolute url, it will not be modified +- if `url` is a relative path, the basePath will be prepended using `basePath.prepend` +- if `url` is a `{ path: string; prependBasePath: boolean }` structure: + - if `prependBasePath` is true, the basePath will be prepended to the given `path` using `basePath.prepend` + - if `prependBasePath` is false, the given `path` will be returned unmodified + +#### redirecting to a result + +Parsing a relative or absolute result url to perform SPA navigation can be non trivial, and should remains the responsibility +of the GlobalSearch plugin API. + +This is why `NavigableGlobalSearchResult.navigate` has been introduced on the client-side version of the `find` API + +When using `navigate` from a result instance, the following logic will be executed: + +If all these criteria are true for `result.url`: + +- (only for absolute URLs) The origin of the URL matches the origin of the browser's current location +- The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) +- The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) + +Then: match the pathname segment to the corresponding application and do the SPA navigation to that application using +`application.navigateToApp` using the remaining pathname segment for the `path` option. + +Otherwise: do a full page navigation using `window.location.assign` + +### searching from the server side + +When calling `GlobalSearchPluginStart.find` from the server-side service: + +- the service will call `find` on each server-side registered result provider and collect the resulting result observables + +- then, the service will merge every result observable and trigger the next step on every emission until either + - A predefined timeout duration is reached + - All result observables are completed + +- on every emission of the merged observable, the results will be processed then emitted. + +A very naive implementation of this behavior would be: + +```ts +search( + term: string, + options: GlobalSearchFindOptions, + request: KibanaRequest +): Observable { + const aborted$ = merge(timeout$, options.$aborted).pipe(first()) + const fromProviders$ = this.providers.map(p => + p.find(term, { ...options, aborted$ }, contextFromRequest(request)) + ); + return merge([...fromProviders$]).pipe( + takeUntil(aborted$), + map(newResults => { + return process(newResults); + }), + ); +} +``` + +### searching from the client side + +When calling `GlobalSearchPluginStart.find` from the public-side service: + +- The service will call: + + - the server-side API via an http call to fetch results from the server-side result providers + - `find` on each client-side registered result provider and collect the resulting observables + +- Then, the service will merge every result observable and trigger the next step on every emission until either + + - A predefined timeout duration is reached + - All result observables are completed + +- on every emission of the merged observable, the results will be processed then emitted. + +A very naive implementation of this behavior would be: + +``` +search( + term: string, + options: GlobalSearchFindOptions, +): Observable { + const aborted$ = merge(timeout$, options.$aborted).pipe(first()) + const fromProviders$ = this.providers.map(p => + p.find(term, { ...options, aborted$ }) + ); + const fromServer$ = of(this.fetchServerResults(term, options, aborted$)) + return merge([...fromProviders$, fromServer$]).pipe( + takeUntil(aborted$), + map(newResults => { + return process(newResults); + }), + ); +} +``` + +Notes: + +- The example implementation is not streaming results from the server, meaning that all results from server-side + registered providers will all be fetched and emitted in a single batch. Ideally, we would leverage the `bfetch` plugin + to stream the results to the client instead. + +### results sorting + +As the GS `find` API is 'streaming' the results from the result providers by emitting the results in batches, sorting results in +each individual batch, even if technically possible, wouldn't provide much value as the consumer will need to sort the +aggregated results on each emission anyway. This is why the results emitted by the `find` API should be considered as +unsorted. Consumers should implement sorting themselves, using either the `score` attribute, or any other arbitrary logic. + +#### Note on score value + +Due to the fact that the results will be coming from various providers, from multiple ES queries or even not from ES, +using a centralized scoring mechanism is not possible. + +the `GlobalSearchResult` contains a `score` field, with an expected value going from 1 (lowest) to 100 (highest). +How this field is populated from each individual provider is considered an implementation detail. + +### Search cancellation + +Consumers can cancel a `find` call at any time by providing a cancellation observable with +the `GlobalSearchFindOptions.aborted$` option and then emitting from it. + +When this observable is provided and emitting, the GS service will complete the result observable. + +This observable will also be passed down to the underlying result providers, that can leverage it to cancel any pending +asynchronous task and perform cleanup if necessary. + +# Drawbacks + +See alternatives. + +# Alternatives + +## Result providers could be only registrable from the server-side API + +The fact that some kinds of results, and therefore some result providers, must be on the client-side makes the API more complex, +while making these results not available from the server-side and HTTP APIs. + +We could decide to only allow providers registration from the server-side. It would reduce API exposure, while simplifying +the service implementation. However to do that, we would need to find a solution to be able to implement a server-side +result provider for `application` (and later `management_section`) type provider. + +I will directly exclude the option to move the `application` registration (`core.application.register`) from client +to server-side, as it's a very heavy impacting (and breaking) change to `core` APIs that would requires more reasons +than just this RFC/API to consider. + +### AST parsing + +One option to make the `application` results 'visible' from the server-side would be to parse the client code at build time +using AST to find all usages to `application.register` inspect the parameters, and generates a server file +containing the applications. The server-side `application` result provider would then just read this file and uses it +to return application results. + +However + +- At the parsing would be done at build time, we would not be able to generate entries for any 3rd party plugins +- As entries for every existing applications would be generated, the search provider would to be able to know which + applications are actually enabled/accessible at runtime to filter them, which is all but easy +- It will also not contains test plugin apps, making it really hard to FTR +- AST parsing is a complex mechanism for an already unsatisfactory alternative + +### Duplicated server-side `application.register` API + +One other option would be to duplicate the `application.register` API on the server side, with a subset of the +client-side metadata. + +```ts +core.application.register({ + id: 'app_status', + title: 'App Status', + euiIconType: 'snowflake', +}); +``` + +This way, the applications could be searchable from the server using this server-side `applications` registry. + +However + +- It forces plugin developers to add this API call. In addition to be a very poor developer experience, it can also + very easily be forgotten, making a given app non searchable +- client-side only plugins would need to add a server-side part to their plugin just to register their application on + the server side + +# Adoption strategy + +The `globalSearch` service is a new feature provided by the `core` API. Also, the base providers +used to search for saved objects and applications will be implemented by the platform team, meaning +that by default, plugin developers won't have to do anything. + +Plugins that wish to expose additional result providers will easily be able to do so by using the exposed APIs and +documentation. + +# How we teach this + +This follows the same patterns we have used for other Core APIs: Observables subscriptions, etc. + +This should be taught using the same channels we've leveraged for other Kibana Platform APIs, API documentation and +example plugins. + +# Unresolved questions + +N/A diff --git a/scripts/es.js b/scripts/es.js index 4f15cc11801e3c..93f1d69350bac2 100644 --- a/scripts/es.js +++ b/scripts/es.js @@ -32,7 +32,7 @@ kbnEs 'base-path': resolve(__dirname, '../.es'), ssl: false, }) - .catch(function(e) { + .catch(function (e) { console.error(e); process.exitCode = 1; }); diff --git a/scripts/kibana.js b/scripts/kibana.js index 4da739469ffb1a..f5a63e6c07dd60 100644 --- a/scripts/kibana.js +++ b/scripts/kibana.js @@ -17,6 +17,6 @@ * under the License. */ -require('../src/setup_node_env'); require('../src/apm')(process.env.ELASTIC_APM_PROXY_SERVICE_NAME || 'kibana-proxy'); +require('../src/setup_node_env'); require('../src/cli/cli'); diff --git a/scripts/test_hardening.js b/scripts/test_hardening.js index c0a20a9ff6cb47..0bc0d1c045ac08 100644 --- a/scripts/test_hardening.js +++ b/scripts/test_hardening.js @@ -28,10 +28,10 @@ program .description( 'Run the tests in test/harden directory. If no files are provided, all files within the directory will be run.' ) - .action(function(globs) { + .action(function (globs) { if (globs.length === 0) globs.push(path.join('test', 'harden', '*')); - globs.forEach(function(glob) { - syncGlob(glob).forEach(function(filename) { + globs.forEach(function (glob) { + syncGlob(glob).forEach(function (filename) { if (path.basename(filename)[0] === '_') return; console.log(process.argv[0], filename); execFileSync(process.argv[0], [filename], { stdio: 'inherit' }); diff --git a/src/apm.js b/src/apm.js index e3f4d84d9b523b..6c10539c6b7d3b 100644 --- a/src/apm.js +++ b/src/apm.js @@ -85,7 +85,7 @@ function getConfig(serviceName) { */ const isKibanaDistributable = Boolean(build && build.distributable === true); -module.exports = function(serviceName = name) { +module.exports = function (serviceName = name) { if (process.env.kbnWorkerType === 'optmzr') return; const conf = getConfig(serviceName); diff --git a/src/cli/cli.js b/src/cli/cli.js index b6598520352a6c..50a8d4c7f7f012 100644 --- a/src/cli/cli.js +++ b/src/cli/cli.js @@ -40,13 +40,13 @@ serveCommand(program); program .command('help ') .description('Get the help for a specific command') - .action(function(cmdName) { + .action(function (cmdName) { const cmd = _.find(program.commands, { _name: cmdName }); if (!cmd) return program.error(`unknown command ${cmdName}`); cmd.help(); }); -program.command('*', null, { noHelp: true }).action(function(cmd) { +program.command('*', null, { noHelp: true }).action(function (cmd) { program.error(`unknown command ${cmd}`); }); diff --git a/src/cli/cluster/cluster_manager.test.ts b/src/cli/cluster/cluster_manager.test.ts index 707778861fb59f..66f68f815edaca 100644 --- a/src/cli/cluster/cluster_manager.test.ts +++ b/src/cli/cluster/cluster_manager.test.ts @@ -153,7 +153,7 @@ describe('CLI cluster manager', () => { const events: Array = []; delayUntil().subscribe( () => events.push('next'), - error => events.push(error), + (error) => events.push(error), () => events.push('complete') ); diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 3b3e4d78320d24..fc94f8d585a020 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -37,7 +37,7 @@ process.env.kbnWorkerType = 'managr'; const firstAllTrue = (...sources: Array>) => Rx.combineLatest(...sources).pipe( - filter(values => values.every(v => v === true)), + filter((values) => values.every((v) => v === true)), take(1), mapTo(undefined) ); @@ -75,7 +75,7 @@ export class ClusterManager { .pipe( map(({ state }) => state.phase === 'success' || state.phase === 'issue'), tap({ - error: error => { + error: (error) => { this.log.bad('New platform optimizer error', error.stack); process.exit(1); }, @@ -139,9 +139,9 @@ export class ClusterManager { .subscribe(this.optimizerReady$); // broker messages between workers - this.workers.forEach(worker => { - worker.on('broadcast', msg => { - this.workers.forEach(to => { + this.workers.forEach((worker) => { + worker.on('broadcast', (msg) => { + this.workers.forEach((to) => { if (to !== worker && to.online) { to.fork!.send(msg); } @@ -156,7 +156,7 @@ export class ClusterManager { this.server.on('reloadLoggingConfigFromServerWorker', () => { process.emit('message' as any, { reloadLoggingConfig: true } as any); - this.workers.forEach(worker => { + this.workers.forEach((worker) => { worker.fork!.send({ reloadLoggingConfig: true }); }); }); @@ -182,7 +182,7 @@ export class ClusterManager { const extraPaths = [...pluginPaths, ...scanDirs]; const pluginInternalDirsIgnore = scanDirs - .map(scanDir => resolve(scanDir, '*')) + .map((scanDir) => resolve(scanDir, '*')) .concat(pluginPaths) .reduce( (acc, path) => @@ -212,10 +212,7 @@ export class ClusterManager { shouldRedirectFromOldBasePath: (path: string) => { // strip `s/{id}` prefix when checking for need to redirect if (path.startsWith('s/')) { - path = path - .split('/') - .slice(2) - .join('/'); + path = path.split('/').slice(2).join('/'); } const isApp = path.startsWith('app/'); @@ -253,7 +250,7 @@ export class ClusterManager { fromRoot('x-pack/legacy/server'), fromRoot('config'), ...extraPaths, - ].map(path => resolve(path)) + ].map((path) => resolve(path)) ) ); diff --git a/src/cli/cluster/run_kbn_optimizer.ts b/src/cli/cluster/run_kbn_optimizer.ts index b811fc1f6b294d..f36ce70f65a45b 100644 --- a/src/cli/cluster/run_kbn_optimizer.ts +++ b/src/cli/cluster/run_kbn_optimizer.ts @@ -33,8 +33,10 @@ import { LegacyConfig } from '../../core/server/legacy'; export function runKbnOptimizer(opts: Record, config: LegacyConfig) { const optimizerConfig = OptimizerConfig.create({ repoRoot: REPO_ROOT, - watch: true, + watch: !!opts.watch, includeCoreBundle: true, + cache: !!opts.cache, + dist: !!opts.dist, oss: !!opts.oss, examples: !!opts.runExamples, pluginPaths: config.get('plugins.paths'), diff --git a/src/cli/cluster/worker.ts b/src/cli/cluster/worker.ts index c73d3edbf7df70..dc6e6d56766510 100644 --- a/src/cli/cluster/worker.ts +++ b/src/cli/cluster/worker.ts @@ -136,7 +136,7 @@ export class Worker extends EventEmitter { this.processBinder.destroy(); // wait until the cluster reports this fork has exited, then resolve - await new Promise(resolve => this.once('fork:exit', resolve)); + await new Promise((resolve) => this.once('fork:exit', resolve)); } } @@ -179,7 +179,7 @@ export class Worker extends EventEmitter { flushChangeBuffer() { const files = _.unique(this.changes.splice(0)); const prefix = files.length > 1 ? '\n - ' : ''; - return files.reduce(function(list, file) { + return files.reduce(function (list, file) { return `${list || ''}${prefix}"${file}"`; }, ''); } @@ -188,7 +188,7 @@ export class Worker extends EventEmitter { if (this.fork) { // once "exit" event is received with 0 status, start() is called again this.shutdown(); - await new Promise(cb => this.once('online', cb)); + await new Promise((cb) => this.once('online', cb)); return; } @@ -214,6 +214,6 @@ export class Worker extends EventEmitter { this.processBinder.on('exit', () => this.shutdown()); // wait for the fork to report it is online before resolving - await new Promise(cb => this.once('fork:online', cb)); + await new Promise((cb) => this.once('fork:online', cb)); } } diff --git a/src/cli/command.js b/src/cli/command.js index 6f083bb2a1fa2a..f4781fcab1e20c 100644 --- a/src/cli/command.js +++ b/src/cli/command.js @@ -23,7 +23,7 @@ import Chalk from 'chalk'; import help from './help'; import { Command } from 'commander'; -Command.prototype.error = function(err) { +Command.prototype.error = function (err) { if (err && err.message) err = err.message; console.log( @@ -37,7 +37,7 @@ ${help(this, ' ')} process.exit(64); // eslint-disable-line no-process-exit }; -Command.prototype.defaultHelp = function() { +Command.prototype.defaultHelp = function () { console.log( ` ${help(this, ' ')} @@ -48,7 +48,7 @@ ${help(this, ' ')} process.exit(64); // eslint-disable-line no-process-exit }; -Command.prototype.unknownArgv = function(argv) { +Command.prototype.unknownArgv = function (argv) { if (argv) this.__unknownArgv = argv; return this.__unknownArgv ? this.__unknownArgv.slice(0) : []; }; @@ -57,11 +57,11 @@ Command.prototype.unknownArgv = function(argv) { * setup the command to accept arbitrary configuration via the cli * @return {[type]} [description] */ -Command.prototype.collectUnknownOptions = function() { +Command.prototype.collectUnknownOptions = function () { const title = `Extra ${this._name} options`; this.allowUnknownOption(); - this.getUnknownOptions = function() { + this.getUnknownOptions = function () { const opts = {}; const unknowns = this.unknownArgv(); @@ -95,17 +95,17 @@ Command.prototype.collectUnknownOptions = function() { return this; }; -Command.prototype.parseOptions = _.wrap(Command.prototype.parseOptions, function(parse, argv) { +Command.prototype.parseOptions = _.wrap(Command.prototype.parseOptions, function (parse, argv) { const opts = parse.call(this, argv); this.unknownArgv(opts.unknown); return opts; }); -Command.prototype.action = _.wrap(Command.prototype.action, function(action, fn) { - return action.call(this, function(...args) { +Command.prototype.action = _.wrap(Command.prototype.action, function (action, fn) { + return action.call(this, function (...args) { const ret = fn.apply(this, args); if (ret && typeof ret.then === 'function') { - ret.then(null, function(e) { + ret.then(null, function (e) { console.log('FATAL CLI ERROR', e.stack); process.exit(1); }); diff --git a/src/cli/help.js b/src/cli/help.js index a2dc638d2b6ee5..656944d85b254d 100644 --- a/src/cli/help.js +++ b/src/cli/help.js @@ -24,7 +24,7 @@ export default function help(command, spaces) { return command.outputHelp(); } - const defCmd = _.find(command.commands, function(cmd) { + const defCmd = _.find(command.commands, function (cmd) { return cmd._name === 'serve'; }); @@ -53,12 +53,12 @@ function indent(str, n) { function commandsSummary(program) { const cmds = _.compact( - program.commands.map(function(cmd) { + program.commands.map(function (cmd) { const name = cmd._name; if (name === '*') return; const opts = cmd.options.length ? ' [options]' : ''; const args = cmd._args - .map(function(arg) { + .map(function (arg) { return humanReadableArgName(arg); }) .join(' '); @@ -67,11 +67,11 @@ function commandsSummary(program) { }) ); - const cmdLColWidth = cmds.reduce(function(width, cmd) { + const cmdLColWidth = cmds.reduce(function (width, cmd) { return Math.max(width, cmd[0].length); }, 0); - return cmds.reduce(function(help, cmd) { + return cmds.reduce(function (help, cmd) { return `${help || ''}${_.padRight(cmd[0], cmdLColWidth)} ${cmd[1] || ''}\n`; }, ''); } diff --git a/src/cli/index.js b/src/cli/index.js index 6dbdd800268a9b..45f88eaf82a5b8 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -17,6 +17,6 @@ * under the License. */ -require('../setup_node_env'); require('../apm')(); +require('../setup_node_env'); require('./cli'); diff --git a/src/cli/repl/index.js b/src/cli/repl/index.js index 37a51b4d1ec9e6..0b27fafcef84eb 100644 --- a/src/cli/repl/index.js +++ b/src/cli/repl/index.js @@ -72,7 +72,7 @@ function prettyPrint(text, o, depth) { // This lets us handle promises more gracefully than the default REPL, // which doesn't show the results. function promiseFriendlyWriter({ displayPrompt, getPrintDepth }) { - return result => promisePrint(result, displayPrompt, getPrintDepth); + return (result) => promisePrint(result, displayPrompt, getPrintDepth); } function promisePrint(result, displayPrompt, getPrintDepth) { @@ -83,8 +83,8 @@ function promisePrint(result, displayPrompt, getPrintDepth) { Promise.resolve() .then(() => console.log('Waiting for promise...')) .then(() => result) - .then(o => prettyPrint('Promise Resolved: \n', o, depth)) - .catch(err => prettyPrint('Promise Rejected: \n', err, depth)) + .then((o) => prettyPrint('Promise Resolved: \n', o, depth)) + .catch((err) => prettyPrint('Promise Rejected: \n', err, depth)) .then(displayPrompt); return ''; } diff --git a/src/cli/repl/repl.test.js b/src/cli/repl/repl.test.js index 9abb43c3382906..3a032d415e5f20 100644 --- a/src/cli/repl/repl.test.js +++ b/src/cli/repl/repl.test.js @@ -17,7 +17,7 @@ * under the License. */ -jest.mock('repl', () => ({ start: opts => ({ opts, context: {} }) }), { virtual: true }); +jest.mock('repl', () => ({ start: (opts) => ({ opts, context: {} }) }), { virtual: true }); describe('repl', () => { const originalConsoleLog = console.log; @@ -25,7 +25,7 @@ describe('repl', () => { beforeEach(() => { global.console.log = jest.fn(); - require('repl').start = opts => { + require('repl').start = (opts) => { let resetHandler; const replServer = { opts, @@ -188,7 +188,7 @@ describe('repl', () => { async function waitForPrompt(replServer, fn) { let resolveDone; - const done = new Promise(resolve => (resolveDone = resolve)); + const done = new Promise((resolve) => (resolveDone = resolve)); replServer.displayPrompt = () => { resolveDone(); }; diff --git a/src/cli/serve/integration_tests/invalid_config.test.ts b/src/cli/serve/integration_tests/invalid_config.test.ts index da6684fae8cefe..fd6fa1bf192fc3 100644 --- a/src/cli/serve/integration_tests/invalid_config.test.ts +++ b/src/cli/serve/integration_tests/invalid_config.test.ts @@ -29,10 +29,10 @@ interface LogEntry { type: string; } -describe('cli invalid config support', function() { +describe('cli invalid config support', function () { it( 'exits with statusCode 64 and logs a single line when config is invalid', - function() { + function () { // Unused keys only throw once LegacyService starts, so disable migrations so that Core // will finish the start lifecycle without a running Elasticsearch instance. const { error, status, stdout } = spawnSync( @@ -47,9 +47,9 @@ describe('cli invalid config support', function() { .toString('utf8') .split('\n') .filter(Boolean) - .map(line => JSON.parse(line) as LogEntry) - .filter(line => line.tags.includes('fatal')) - .map(obj => ({ + .map((line) => JSON.parse(line) as LogEntry) + .filter((line) => line.tags.includes('fatal')) + .map((obj) => ({ ...obj, pid: '## PID ##', '@timestamp': '## @timestamp ##', diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.ts b/src/cli/serve/integration_tests/reload_logging_config.test.ts index 9ad8438c312a1e..35391b9b58ecc5 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.ts +++ b/src/cli/serve/integration_tests/reload_logging_config.test.ts @@ -70,7 +70,7 @@ function watchFileUntil(path: string, matcher: RegExp, timeout: number) { } function containsJsonOnly(content: string[]) { - return content.every(line => line.startsWith('{')); + return content.every((line) => line.startsWith('{')); } function createConfigManager(configPath: string) { @@ -83,7 +83,7 @@ function createConfigManager(configPath: string) { }; } -describe('Server logging configuration', function() { +describe('Server logging configuration', function () { let child: undefined | Child.ChildProcess; beforeEach(() => { @@ -92,7 +92,7 @@ describe('Server logging configuration', function() { afterEach(async () => { if (child !== undefined) { - const exitPromise = new Promise(resolve => child?.once('exit', resolve)); + const exitPromise = new Promise((resolve) => child?.once('exit', resolve)); child.kill('SIGKILL'); await exitPromise; } @@ -110,7 +110,7 @@ describe('Server logging configuration', function() { describe('legacy logging', () => { it( 'should be reloadable via SIGHUP process signaling', - async function() { + async function () { const configFilePath = Path.resolve(tempDir, 'kibana.yml'); Fs.copyFileSync(legacyConfig, configFilePath); @@ -123,17 +123,13 @@ describe('Server logging configuration', function() { ]); const message$ = Rx.fromEvent(child.stdout, 'data').pipe( - map(messages => - String(messages) - .split('\n') - .filter(Boolean) - ) + map((messages) => String(messages).split('\n').filter(Boolean)) ); await message$ .pipe( // We know the sighup handler will be registered before this message logged - filter(messages => messages.some(m => m.includes('setting up root'))), + filter((messages) => messages.some((m) => m.includes('setting up root'))), take(1) ) .toPromise(); @@ -141,7 +137,7 @@ describe('Server logging configuration', function() { const lastMessage = await message$.pipe(take(1)).toPromise(); expect(containsJsonOnly(lastMessage)).toBe(true); - createConfigManager(configFilePath).modify(oldConfig => { + createConfigManager(configFilePath).modify((oldConfig) => { oldConfig.logging.json = false; return oldConfig; }); @@ -150,7 +146,7 @@ describe('Server logging configuration', function() { await message$ .pipe( - filter(messages => !containsJsonOnly(messages)), + filter((messages) => !containsJsonOnly(messages)), take(1) ) .toPromise(); @@ -160,7 +156,7 @@ describe('Server logging configuration', function() { it( 'should recreate file handle on SIGHUP', - async function() { + async function () { const logPath = Path.resolve(tempDir, 'kibana.log'); const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); @@ -188,24 +184,20 @@ describe('Server logging configuration', function() { describe('platform logging', () => { it( 'should be reloadable via SIGHUP process signaling', - async function() { + async function () { const configFilePath = Path.resolve(tempDir, 'kibana.yml'); Fs.copyFileSync(configFileLogConsole, configFilePath); child = Child.spawn(process.execPath, [kibanaPath, '--oss', '--config', configFilePath]); const message$ = Rx.fromEvent(child.stdout, 'data').pipe( - map(messages => - String(messages) - .split('\n') - .filter(Boolean) - ) + map((messages) => String(messages).split('\n').filter(Boolean)) ); await message$ .pipe( // We know the sighup handler will be registered before this message logged - filter(messages => messages.some(m => m.includes('setting up root'))), + filter((messages) => messages.some((m) => m.includes('setting up root'))), take(1) ) .toPromise(); @@ -213,7 +205,7 @@ describe('Server logging configuration', function() { const lastMessage = await message$.pipe(take(1)).toPromise(); expect(containsJsonOnly(lastMessage)).toBe(true); - createConfigManager(configFilePath).modify(oldConfig => { + createConfigManager(configFilePath).modify((oldConfig) => { oldConfig.logging.appenders.console.layout.kind = 'pattern'; return oldConfig; }); @@ -221,7 +213,7 @@ describe('Server logging configuration', function() { await message$ .pipe( - filter(messages => !containsJsonOnly(messages)), + filter((messages) => !containsJsonOnly(messages)), take(1) ) .toPromise(); @@ -230,14 +222,14 @@ describe('Server logging configuration', function() { ); it( 'should recreate file handle on SIGHUP', - async function() { + async function () { const configFilePath = Path.resolve(tempDir, 'kibana.yml'); Fs.copyFileSync(configFileLogFile, configFilePath); const logPath = Path.resolve(tempDir, 'kibana.log'); const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); - createConfigManager(configFilePath).modify(oldConfig => { + createConfigManager(configFilePath).modify((oldConfig) => { oldConfig.logging.appenders.file.path = logPath; return oldConfig; }); diff --git a/src/cli/serve/read_keystore.js b/src/cli/serve/read_keystore.js index c17091a11f5c14..cfe02735630f22 100644 --- a/src/cli/serve/read_keystore.js +++ b/src/cli/serve/read_keystore.js @@ -30,7 +30,7 @@ export function readKeystore(dataPath = getDataPath()) { const keys = Object.keys(keystore.data); const data = {}; - keys.forEach(key => { + keys.forEach((key) => { set(data, key, keystore.data[key]); }); diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 471939121143a1..8bc65f3da7111e 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -52,9 +52,9 @@ const CAN_REPL = canRequire(REPL_PATH); const XPACK_DIR = resolve(__dirname, '../../../x-pack'); const XPACK_INSTALLED = canRequire(XPACK_DIR); -const pathCollector = function() { +const pathCollector = function () { const paths = []; - return function(path) { + return function (path) { paths.push(resolve(process.cwd(), path)); return paths; }; @@ -109,7 +109,7 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { (customElasticsearchHosts.length > 0 && customElasticsearchHosts) || [ 'https://localhost:9200', ] - ).map(hostUrl => { + ).map((hostUrl) => { const parsedUrl = url.parse(hostUrl); if (parsedUrl.hostname !== 'localhost') { throw new Error( @@ -159,7 +159,7 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { return rawConfig; } -export default function(program) { +export default function (program) { const command = program.command('serve'); command @@ -213,15 +213,17 @@ export default function(program) { .option('--dev', 'Run the server with development mode defaults') .option('--open', 'Open a browser window to the base url after the server is started') .option('--ssl', 'Run the dev server using HTTPS') + .option('--dist', 'Use production assets from kbn/optimizer') .option( '--no-base-path', "Don't put a proxy in front of the dev server, which adds a random basePath" ) .option('--no-watch', 'Prevents automatic restarts of the server in --dev mode') + .option('--no-cache', 'Disable the kbn/optimizer cache') .option('--no-dev-config', 'Prevents loading the kibana.dev.yml file in --dev mode'); } - command.action(async function(opts) { + command.action(async function (opts) { if (opts.dev && opts.devConfig !== false) { try { const kbnDevConfig = fromRoot('config/kibana.dev.yml'); @@ -253,12 +255,14 @@ export default function(program) { basePath: opts.runExamples ? false : !!opts.basePath, optimize: !!opts.optimize, oss: !!opts.oss, + cache: !!opts.cache, + dist: !!opts.dist, }, features: { isClusterModeSupported: CAN_CLUSTER, isReplModeSupported: CAN_REPL, }, - applyConfigOverrides: rawConfig => applyConfigOverrides(rawConfig, opts, unknownOptions), + applyConfigOverrides: (rawConfig) => applyConfigOverrides(rawConfig, opts, unknownOptions), }); }); } diff --git a/src/cli_keystore/add.test.js b/src/cli_keystore/add.test.js index 72f15a5439ef0c..320581b470c2b4 100644 --- a/src/cli_keystore/add.test.js +++ b/src/cli_keystore/add.test.js @@ -23,14 +23,14 @@ const mockKeystoreData = 'Ry21UcAJki2qFUTj4TYuvhta3LId+RM5UX/dJ2468hQ=='; jest.mock('fs', () => ({ - readFileSync: jest.fn().mockImplementation(path => { + readFileSync: jest.fn().mockImplementation((path) => { if (!path.includes('nonexistent')) { return JSON.stringify(mockKeystoreData); } throw { code: 'ENOENT' }; }), - existsSync: jest.fn().mockImplementation(path => { + existsSync: jest.fn().mockImplementation((path) => { return !path.includes('nonexistent'); }), writeFileSync: jest.fn(), diff --git a/src/cli_keystore/cli_keystore.js b/src/cli_keystore/cli_keystore.js index 7c90d88f7b0cde..e1561b343ef391 100644 --- a/src/cli_keystore/cli_keystore.js +++ b/src/cli_keystore/cli_keystore.js @@ -50,13 +50,13 @@ removeCli(program, keystore); program .command('help ') .description('get the help for a specific command') - .action(function(cmdName) { + .action(function (cmdName) { const cmd = _.find(program.commands, { _name: cmdName }); if (!cmd) return program.error(`unknown command ${cmdName}`); cmd.help(); }); -program.command('*', null, { noHelp: true }).action(function(cmd) { +program.command('*', null, { noHelp: true }).action(function (cmd) { program.error(`unknown command ${cmd}`); }); diff --git a/src/cli_keystore/create.test.js b/src/cli_keystore/create.test.js index 01355f51a0c55d..33b5aa4bd07d8e 100644 --- a/src/cli_keystore/create.test.js +++ b/src/cli_keystore/create.test.js @@ -23,14 +23,14 @@ const mockKeystoreData = 'Ry21UcAJki2qFUTj4TYuvhta3LId+RM5UX/dJ2468hQ=='; jest.mock('fs', () => ({ - readFileSync: jest.fn().mockImplementation(path => { + readFileSync: jest.fn().mockImplementation((path) => { if (!path.includes('foo')) { return JSON.stringify(mockKeystoreData); } throw { code: 'ENOENT' }; }), - existsSync: jest.fn().mockImplementation(path => { + existsSync: jest.fn().mockImplementation((path) => { return !path.includes('foo'); }), writeFileSync: jest.fn(), diff --git a/src/cli_keystore/list.test.js b/src/cli_keystore/list.test.js index 3fb50148208656..857991b5ae3b9c 100644 --- a/src/cli_keystore/list.test.js +++ b/src/cli_keystore/list.test.js @@ -23,14 +23,14 @@ const mockKeystoreData = 'Ry21UcAJki2qFUTj4TYuvhta3LId+RM5UX/dJ2468hQ=='; jest.mock('fs', () => ({ - readFileSync: jest.fn().mockImplementation(path => { + readFileSync: jest.fn().mockImplementation((path) => { if (!path.includes('nonexistent')) { return JSON.stringify(mockKeystoreData); } throw { code: 'ENOENT' }; }), - existsSync: jest.fn().mockImplementation(path => { + existsSync: jest.fn().mockImplementation((path) => { return !path.includes('nonexistent'); }), })); diff --git a/src/cli_plugin/cli.js b/src/cli_plugin/cli.js index d1cdf983c0da47..da1068b54b4b55 100644 --- a/src/cli_plugin/cli.js +++ b/src/cli_plugin/cli.js @@ -43,13 +43,13 @@ removeCommand(program); program .command('help ') .description('get the help for a specific command') - .action(function(cmdName) { + .action(function (cmdName) { const cmd = _.find(program.commands, { _name: cmdName }); if (!cmd) return program.error(`unknown command ${cmdName}`); cmd.help(); }); -program.command('*', null, { noHelp: true }).action(function(cmd) { +program.command('*', null, { noHelp: true }).action(function (cmd) { program.error(`unknown command ${cmd}`); }); diff --git a/src/cli_plugin/install/cleanup.js b/src/cli_plugin/install/cleanup.js index eaa25962ef0e44..f31e028226c277 100644 --- a/src/cli_plugin/install/cleanup.js +++ b/src/cli_plugin/install/cleanup.js @@ -21,7 +21,7 @@ import del from 'del'; import fs from 'fs'; export function cleanPrevious(settings, logger) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { try { fs.statSync(settings.workingPath); diff --git a/src/cli_plugin/install/cleanup.test.js b/src/cli_plugin/install/cleanup.test.js index c6602636cb4811..46089f61d5e83e 100644 --- a/src/cli_plugin/install/cleanup.test.js +++ b/src/cli_plugin/install/cleanup.test.js @@ -24,32 +24,32 @@ import del from 'del'; import { cleanPrevious, cleanArtifacts } from './cleanup'; import Logger from '../lib/logger'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('pluginCleaner', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('pluginCleaner', function () { const settings = { workingPath: 'dummy', }; - describe('cleanPrevious', function() { + describe('cleanPrevious', function () { let errorStub; let logger; - beforeEach(function() { + beforeEach(function () { errorStub = sinon.stub(); logger = new Logger(settings); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); fs.statSync.restore(); del.sync.restore(); }); - it('should resolve if the working path does not exist', function() { + it('should resolve if the working path does not exist', function () { sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync').callsFake(() => { const error = new Error('ENOENT'); @@ -59,75 +59,75 @@ describe('kibana cli', function() { return cleanPrevious(settings, logger) .catch(errorStub) - .then(function() { + .then(function () { expect(errorStub.called).toBe(false); }); }); - it('should rethrow any exception except ENOENT from fs.statSync', function() { + it('should rethrow any exception except ENOENT from fs.statSync', function () { sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync').throws(new Error('An Unhandled Error')); errorStub = sinon.stub(); return cleanPrevious(settings, logger) .catch(errorStub) - .then(function() { + .then(function () { expect(errorStub.called).toBe(true); }); }); - it('should log a message if there was a working directory', function() { + it('should log a message if there was a working directory', function () { sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync'); return cleanPrevious(settings, logger) .catch(errorStub) - .then(function() { + .then(function () { expect(logger.log.calledWith('Found previous install attempt. Deleting...')).toBe( true ); }); }); - it('should rethrow any exception from del.sync', function() { + it('should rethrow any exception from del.sync', function () { sinon.stub(fs, 'statSync'); sinon.stub(del, 'sync').throws(new Error('I am an error thrown by del')); errorStub = sinon.stub(); return cleanPrevious(settings, logger) .catch(errorStub) - .then(function() { + .then(function () { expect(errorStub.called).toBe(true); }); }); - it('should resolve if the working path is deleted', function() { + it('should resolve if the working path is deleted', function () { sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync'); return cleanPrevious(settings, logger) .catch(errorStub) - .then(function() { + .then(function () { expect(errorStub.called).toBe(false); }); }); }); - describe('cleanArtifacts', function() { - beforeEach(function() {}); + describe('cleanArtifacts', function () { + beforeEach(function () {}); - afterEach(function() { + afterEach(function () { del.sync.restore(); }); - it('should attempt to delete the working directory', function() { + it('should attempt to delete the working directory', function () { sinon.stub(del, 'sync'); cleanArtifacts(settings); expect(del.sync.calledWith(settings.workingPath)).toBe(true); }); - it('should swallow any errors thrown by del.sync', function() { + it('should swallow any errors thrown by del.sync', function () { sinon.stub(del, 'sync').throws(new Error('Something bad happened.')); expect(() => cleanArtifacts(settings)).not.toThrow(); diff --git a/src/cli_plugin/install/download.js b/src/cli_plugin/install/download.js index fc1fe8323520b6..10d20367c1b7ba 100644 --- a/src/cli_plugin/install/download.js +++ b/src/cli_plugin/install/download.js @@ -80,7 +80,7 @@ export function download(settings, logger) { logger.log(`Attempting to transfer from ${sourceUrl}`); - return _downloadSingle(settings, logger, sourceUrl).catch(err => { + return _downloadSingle(settings, logger, sourceUrl).catch((err) => { const isUnsupportedProtocol = err instanceof UnsupportedProtocolError; const isDownloadResourceNotFound = err.message === 'ENOTFOUND'; if (isUnsupportedProtocol || isDownloadResourceNotFound) { diff --git a/src/cli_plugin/install/download.test.js b/src/cli_plugin/install/download.test.js index ef924f28a65e71..93e5e414fed740 100644 --- a/src/cli_plugin/install/download.test.js +++ b/src/cli_plugin/install/download.test.js @@ -28,8 +28,8 @@ import { download, _downloadSingle, _getFilePath, _checkFilePathDeprecation } fr import { join } from 'path'; import http from 'http'; -describe('kibana cli', function() { - describe('plugin downloader', function() { +describe('kibana cli', function () { + describe('plugin downloader', function () { const testWorkingPath = join(__dirname, '.test.data.download'); const tempArchiveFilePath = join(testWorkingPath, 'archive.part'); @@ -57,46 +57,44 @@ describe('kibana cli', function() { throw new Error('expected the promise to reject'); } - beforeEach(function() { + beforeEach(function () { sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); del.sync(testWorkingPath); Fs.mkdirSync(testWorkingPath, { recursive: true }); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); del.sync(testWorkingPath); }); - describe('_downloadSingle', function() { - beforeEach(function() {}); + describe('_downloadSingle', function () { + beforeEach(function () {}); - describe('http downloader', function() { - it('should throw an ENOTFOUND error for a http ulr that returns 404', function() { - nock('http://example.com') - .get('/plugin.tar.gz') - .reply(404); + describe('http downloader', function () { + it('should throw an ENOTFOUND error for a http ulr that returns 404', function () { + nock('http://example.com').get('/plugin.tar.gz').reply(404); const sourceUrl = 'http://example.com/plugin.tar.gz'; - return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function(err) { + return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function (err) { expect(err.message).toMatch(/ENOTFOUND/); expectWorkingPathEmpty(); }); }); - it('should throw an UnsupportedProtocolError for an invalid url', function() { + it('should throw an UnsupportedProtocolError for an invalid url', function () { const sourceUrl = 'i am an invalid url'; - return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function(err) { + return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function (err) { expect(err).toBeInstanceOf(UnsupportedProtocolError); expectWorkingPathEmpty(); }); }); - it('should download a file from a valid http url', function() { + it('should download a file from a valid http url', function () { const filePath = join(__dirname, '__fixtures__/replies/banana.jpg'); nock('http://example.com') @@ -109,40 +107,40 @@ describe('kibana cli', function() { const sourceUrl = 'http://example.com/plugin.zip'; - return _downloadSingle(settings, logger, sourceUrl).then(function() { + return _downloadSingle(settings, logger, sourceUrl).then(function () { expectWorkingPathNotEmpty(); }); }); }); - describe('local file downloader', function() { - it('should throw an ENOTFOUND error for an invalid local file', function() { + describe('local file downloader', function () { + it('should throw an ENOTFOUND error for an invalid local file', function () { const filePath = join(__dirname, '__fixtures__/replies/i-am-not-there.zip'); const sourceUrl = 'file://' + filePath.replace(/\\/g, '/'); - return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function(err) { + return _downloadSingle(settings, logger, sourceUrl).then(shouldReject, function (err) { expect(err.message).toMatch(/ENOTFOUND/); expectWorkingPathEmpty(); }); }); - it('should copy a valid local file', function() { + it('should copy a valid local file', function () { const filePath = join(__dirname, '__fixtures__/replies/banana.jpg'); const sourceUrl = 'file://' + filePath.replace(/\\/g, '/'); - return _downloadSingle(settings, logger, sourceUrl).then(function() { + return _downloadSingle(settings, logger, sourceUrl).then(function () { expectWorkingPathNotEmpty(); }); }); }); }); - describe('_getFilePath', function() { - it('should decode paths', function() { + describe('_getFilePath', function () { + it('should decode paths', function () { expect(_getFilePath('Test%20folder/file.zip')).toBe('Test folder/file.zip'); }); - it('should remove the leading slash from windows paths', function() { + it('should remove the leading slash from windows paths', function () { const platform = Object.getOwnPropertyDescriptor(process, 'platform'); Object.defineProperty(process, 'platform', { value: 'win32' }); @@ -152,8 +150,8 @@ describe('kibana cli', function() { }); }); - describe('Windows file:// deprecation', function() { - it('should log a warning if a file:// path is used', function() { + describe('Windows file:// deprecation', function () { + it('should log a warning if a file:// path is used', function () { const platform = Object.getOwnPropertyDescriptor(process, 'platform'); Object.defineProperty(process, 'platform', { value: 'win32' }); const logger = { @@ -169,8 +167,8 @@ describe('kibana cli', function() { }); }); - describe('download', function() { - it('should loop through bad urls until it finds a good one.', function() { + describe('download', function () { + it('should loop through bad urls until it finds a good one.', function () { const filePath = join(__dirname, '__fixtures__/replies/test_plugin.zip'); settings.urls = [ 'http://example.com/badfile1.tar.gz', @@ -190,7 +188,7 @@ describe('kibana cli', function() { .get('/goodfile.tar.gz') .replyWithFile(200, filePath); - return download(settings, logger).then(function() { + return download(settings, logger).then(function () { expect(logger.log.getCall(0).args[0]).toMatch(/badfile1.tar.gz/); expect(logger.log.getCall(1).args[0]).toMatch(/badfile2.tar.gz/); expect(logger.log.getCall(2).args[0]).toMatch(/I am a bad uri/); @@ -199,7 +197,7 @@ describe('kibana cli', function() { }); }); - it('should stop looping through urls when it finds a good one.', function() { + it('should stop looping through urls when it finds a good one.', function () { const filePath = join(__dirname, '__fixtures__/replies/test_plugin.zip'); settings.urls = [ 'http://example.com/badfile1.tar.gz', @@ -221,7 +219,7 @@ describe('kibana cli', function() { .get('/badfile3.tar.gz') .reply(404); - return download(settings, logger).then(function() { + return download(settings, logger).then(function () { for (let i = 0; i < logger.log.callCount; i++) { expect(logger.log.getCall(i).args[0]).not.toMatch(/badfile3.tar.gz/); } @@ -229,7 +227,7 @@ describe('kibana cli', function() { }); }); - it("should throw an error when it doesn't find a good url.", function() { + it("should throw an error when it doesn't find a good url.", function () { settings.urls = [ 'http://example.com/badfile1.tar.gz', 'http://example.com/badfile2.tar.gz', @@ -247,25 +245,25 @@ describe('kibana cli', function() { .get('/badfile3.tar.gz') .reply(404); - return download(settings, logger).then(shouldReject, function(err) { + return download(settings, logger).then(shouldReject, function (err) { expect(err.message).toMatch(/no valid url specified/i); expectWorkingPathEmpty(); }); }); - afterAll(function() { + afterAll(function () { nock.cleanAll(); }); }); - describe('proxy support', function() { + describe('proxy support', function () { const proxyPort = 2626; const proxyUrl = `http://localhost:${proxyPort}`; let proxyHit = false; let proxyConnectHit = false; - const proxy = http.createServer(function(req, res) { + const proxy = http.createServer(function (req, res) { proxyHit = true; // Our test proxy simply returns an empty 200 response, since we only // care about the download promise being resolved. @@ -301,29 +299,29 @@ describe('kibana cli', function() { .replyWithFile(200, join(__dirname, '__fixtures__/replies/test_plugin.zip')); } - beforeAll(function(done) { + beforeAll(function (done) { proxy.listen(proxyPort, done); }); - beforeEach(function() { + beforeEach(function () { proxyHit = false; proxyConnectHit = false; }); - afterEach(function() { + afterEach(function () { delete process.env.http_proxy; delete process.env.https_proxy; delete process.env.no_proxy; }); - it('should use http_proxy env variable', function() { + it('should use http_proxy env variable', function () { process.env.http_proxy = proxyUrl; settings.urls = ['http://example.com/plugin.zip']; return download(settings, logger).then(expectProxyHit); }); - it('should use https_proxy for secure URLs', function() { + it('should use https_proxy for secure URLs', function () { process.env.https_proxy = proxyUrl; settings.urls = ['https://example.com/plugin.zip']; @@ -340,7 +338,7 @@ describe('kibana cli', function() { ); }); - it('should not use http_proxy for HTTPS urls', function() { + it('should not use http_proxy for HTTPS urls', function () { process.env.http_proxy = proxyUrl; settings.urls = ['https://example.com/plugin.zip']; @@ -349,7 +347,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should not use https_proxy for HTTP urls', function() { + it('should not use https_proxy for HTTP urls', function () { process.env.https_proxy = proxyUrl; settings.urls = ['http://example.com/plugin.zip']; @@ -358,7 +356,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should support domains in no_proxy', function() { + it('should support domains in no_proxy', function () { process.env.http_proxy = proxyUrl; process.env.no_proxy = 'foo.bar, example.com'; settings.urls = ['http://example.com/plugin.zip']; @@ -368,7 +366,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should support subdomains in no_proxy', function() { + it('should support subdomains in no_proxy', function () { process.env.http_proxy = proxyUrl; process.env.no_proxy = 'foo.bar,plugins.example.com'; settings.urls = ['http://plugins.example.com/plugin.zip']; @@ -378,7 +376,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should accept wildcard subdomains in no_proxy', function() { + it('should accept wildcard subdomains in no_proxy', function () { process.env.http_proxy = proxyUrl; process.env.no_proxy = 'foo.bar, .example.com'; settings.urls = ['http://plugins.example.com/plugin.zip']; @@ -388,7 +386,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should support asterisk wildcard no_proxy syntax', function() { + it('should support asterisk wildcard no_proxy syntax', function () { process.env.http_proxy = proxyUrl; process.env.no_proxy = '*.example.com'; settings.urls = ['http://plugins.example.com/plugin.zip']; @@ -398,7 +396,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - it('should support implicit ports in no_proxy', function() { + it('should support implicit ports in no_proxy', function () { process.env.https_proxy = proxyUrl; process.env.no_proxy = 'example.com:443'; settings.urls = ['https://example.com/plugin.zip']; @@ -408,7 +406,7 @@ describe('kibana cli', function() { return download(settings, logger).then(expectNoProxyHit); }); - afterAll(function(done) { + afterAll(function (done) { proxy.close(done); }); }); diff --git a/src/cli_plugin/install/downloaders/file.js b/src/cli_plugin/install/downloaders/file.js index eee8ddb21d6dd5..56f83b03d5a907 100644 --- a/src/cli_plugin/install/downloaders/file.js +++ b/src/cli_plugin/install/downloaders/file.js @@ -43,7 +43,7 @@ async function copyFile({ readStream, writeStream, progress }) { writeStream.on('error', reject); // report progress as we transfer - readStream.on('data', chunk => { + readStream.on('data', (chunk) => { progress.progress(chunk.length); }); diff --git a/src/cli_plugin/install/downloaders/http.js b/src/cli_plugin/install/downloaders/http.js index 88dcdabe70dfd9..0fc01453f2b4c4 100644 --- a/src/cli_plugin/install/downloaders/http.js +++ b/src/cli_plugin/install/downloaders/http.js @@ -76,7 +76,7 @@ function downloadResponse({ resp, targetPath, progress }) { writeStream.on('error', reject); // report progress as we download - resp.on('data', chunk => { + resp.on('data', (chunk) => { progress.progress(chunk.length); }); diff --git a/src/cli_plugin/install/index.test.js b/src/cli_plugin/install/index.test.js index 6a64a673bb93e5..39352f52f20fde 100644 --- a/src/cli_plugin/install/index.test.js +++ b/src/cli_plugin/install/index.test.js @@ -20,25 +20,25 @@ import sinon from 'sinon'; import index from './index'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('commander options', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('commander options', function () { const program = { - command: function() { + command: function () { return program; }, - description: function() { + description: function () { return program; }, - option: function() { + option: function () { return program; }, - action: function() { + action: function () { return program; }, }; - it('should define the command', function() { + it('should define the command', function () { sinon.spy(program, 'command'); index(program); @@ -47,7 +47,7 @@ describe('kibana cli', function() { program.command.restore(); }); - it('should define the description', function() { + it('should define the description', function () { sinon.spy(program, 'description'); index(program); @@ -56,7 +56,7 @@ describe('kibana cli', function() { program.description.restore(); }); - it('should define the command line options', function() { + it('should define the command line options', function () { const spy = sinon.spy(program, 'option'); const options = [/-q/, /-s/, /-c/, /-t/, /-d/]; @@ -77,7 +77,7 @@ describe('kibana cli', function() { expect(options).toHaveLength(0); }); - it('should call the action function', function() { + it('should call the action function', function () { sinon.spy(program, 'action'); index(program); diff --git a/src/cli_plugin/install/kibana.test.js b/src/cli_plugin/install/kibana.test.js index bbf364a755f8a0..8c5dd00d099531 100644 --- a/src/cli_plugin/install/kibana.test.js +++ b/src/cli_plugin/install/kibana.test.js @@ -30,9 +30,9 @@ beforeEach(() => { jest.clearAllMocks(); }); -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('kibana', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('kibana', function () { const testWorkingPath = join(__dirname, '.test.data.kibana'); const tempArchiveFilePath = join(testWorkingPath, 'archive.part'); const pluginDir = join(__dirname, 'plugins'); @@ -48,21 +48,21 @@ describe('kibana cli', function() { const logger = new Logger(settings); - describe('assertVersion', function() { - beforeEach(function() { + describe('assertVersion', function () { + beforeEach(function () { del.sync(testWorkingPath); fs.mkdirSync(testWorkingPath, { recursive: true }); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); del.sync(testWorkingPath); }); - it('should succeed with exact match', function() { + it('should succeed with exact match', function () { const settings = { workingPath: testWorkingPath, tempArchiveFile: tempArchiveFilePath, @@ -76,60 +76,60 @@ describe('kibana cli', function() { expect(() => assertVersion(settings)).not.toThrow(); }); - it('should throw an error if plugin is missing a kibana version.', function() { + it('should throw an error if plugin is missing a kibana version.', function () { expect(() => assertVersion(settings)).toThrow( /plugin package\.json is missing both a version property/i ); }); - it('should throw an error if plugin kibanaVersion does not match kibana version', function() { + it('should throw an error if plugin kibanaVersion does not match kibana version', function () { settings.plugins[0].kibanaVersion = '1.2.3.4'; expect(() => assertVersion(settings)).toThrow(/incompatible with Kibana/i); }); - it('should not throw an error if plugin kibanaVersion matches kibana version', function() { + it('should not throw an error if plugin kibanaVersion matches kibana version', function () { settings.plugins[0].kibanaVersion = '1.0.0'; expect(() => assertVersion(settings)).not.toThrow(); }); - it('should ignore version info after the dash in checks on valid version', function() { + it('should ignore version info after the dash in checks on valid version', function () { settings.plugins[0].kibanaVersion = '1.0.0-foo-bar-version-1.2.3'; expect(() => assertVersion(settings)).not.toThrow(); }); - it('should ignore version info after the dash in checks on invalid version', function() { + it('should ignore version info after the dash in checks on invalid version', function () { settings.plugins[0].kibanaVersion = '2.0.0-foo-bar-version-1.2.3'; expect(() => assertVersion(settings)).toThrow(/incompatible with Kibana/i); }); }); - describe('existingInstall', function() { + describe('existingInstall', function () { let processExitStub; - beforeEach(function() { + beforeEach(function () { processExitStub = sinon.stub(process, 'exit'); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); }); - afterEach(function() { + afterEach(function () { processExitStub.restore(); logger.log.restore(); logger.error.restore(); }); - it('should throw an error if the plugin already exists.', function() { + it('should throw an error if the plugin already exists.', function () { fs.statSync.mockImplementationOnce(() => true); existingInstall(settings, logger); expect(logger.error.firstCall.args[0]).toMatch(/already exists/); expect(process.exit.called).toBe(true); }); - it('should not throw an error if the plugin does not exist.', function() { + it('should not throw an error if the plugin does not exist.', function () { fs.statSync.mockImplementationOnce(() => { throw { code: 'ENOENT' }; }); diff --git a/src/cli_plugin/install/pack.test.js b/src/cli_plugin/install/pack.test.js index efe310a4fed404..05a60107f80ff8 100644 --- a/src/cli_plugin/install/pack.test.js +++ b/src/cli_plugin/install/pack.test.js @@ -27,8 +27,8 @@ import { extract, getPackData } from './pack'; import { _downloadSingle } from './download'; import { join } from 'path'; -describe('kibana cli', function() { - describe('pack', function() { +describe('kibana cli', function () { + describe('pack', function () { let testNum = 0; const workingPathRoot = join(__dirname, '.test.data.pack'); let testWorkingPath; @@ -37,7 +37,7 @@ describe('kibana cli', function() { let logger; let settings; - beforeEach(function() { + beforeEach(function () { //These tests are dependent on the file system, and I had some inconsistent //behavior with del.sync show up. Until these tests are re-written to not //depend on the file system, I make sure that each test uses a different @@ -60,7 +60,7 @@ describe('kibana cli', function() { Fs.mkdirSync(testWorkingPath, { recursive: true }); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); del.sync(workingPathRoot); @@ -77,10 +77,10 @@ describe('kibana cli', function() { throw new Error('expected the promise to reject'); } - describe('extract', function() { + describe('extract', function () { //Also only extracts the content from the kibana folder. //Ignores the others. - it('successfully extract a valid zip', function() { + it('successfully extract a valid zip', function () { return copyReplyFile('test_plugin.zip') .then(() => { return getPackData(settings, logger); @@ -104,8 +104,8 @@ describe('kibana cli', function() { }); }); - describe('getPackData', function() { - it('populate settings.plugins', function() { + describe('getPackData', function () { + it('populate settings.plugins', function () { return copyReplyFile('test_plugin.zip') .then(() => { return getPackData(settings, logger); @@ -118,7 +118,7 @@ describe('kibana cli', function() { }); }); - it('populate settings.plugin.kibanaVersion', function() { + it('populate settings.plugin.kibanaVersion', function () { //kibana.version is defined in this package.json and is different than plugin version return copyReplyFile('test_plugin_different_version.zip') .then(() => { @@ -129,7 +129,7 @@ describe('kibana cli', function() { }); }); - it('populate settings.plugin.kibanaVersion (default to plugin version)', function() { + it('populate settings.plugin.kibanaVersion (default to plugin version)', function () { //kibana.version is not defined in this package.json, defaults to plugin version return copyReplyFile('test_plugin.zip') .then(() => { @@ -140,7 +140,7 @@ describe('kibana cli', function() { }); }); - it('populate settings.plugins with multiple plugins', function() { + it('populate settings.plugins with multiple plugins', function () { return copyReplyFile('test_plugin_many.zip') .then(() => { return getPackData(settings, logger); @@ -172,32 +172,32 @@ describe('kibana cli', function() { }); }); - it('throw an error if there is no kibana plugin', function() { + it('throw an error if there is no kibana plugin', function () { return copyReplyFile('test_plugin_no_kibana.zip') .then(() => { return getPackData(settings, logger); }) - .then(shouldReject, err => { + .then(shouldReject, (err) => { expect(err.message).toMatch(/No kibana plugins found in archive/i); }); }); - it('throw an error with a corrupt zip', function() { + it('throw an error with a corrupt zip', function () { return copyReplyFile('corrupt.zip') .then(() => { return getPackData(settings, logger); }) - .then(shouldReject, err => { + .then(shouldReject, (err) => { expect(err.message).toMatch(/error retrieving/i); }); }); - it('throw an error if there an invalid plugin name', function() { + it('throw an error if there an invalid plugin name', function () { return copyReplyFile('invalid_name.zip') .then(() => { return getPackData(settings, logger); }) - .then(shouldReject, err => { + .then(shouldReject, (err) => { expect(err.message).toMatch(/invalid plugin name/i); }); }); diff --git a/src/cli_plugin/install/progress.test.js b/src/cli_plugin/install/progress.test.js index 5430af75968bbb..3b66e8b3dc86c9 100644 --- a/src/cli_plugin/install/progress.test.js +++ b/src/cli_plugin/install/progress.test.js @@ -21,26 +21,26 @@ import sinon from 'sinon'; import Progress from './progress'; import Logger from '../lib/logger'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('progressReporter', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('progressReporter', function () { let logger; let progress; - beforeEach(function() { + beforeEach(function () { logger = new Logger({ silent: false, quiet: false }); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); progress = new Progress(logger); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); }); - describe('handleData', function() { - it('should show a max of 20 dots for full progress', function() { + describe('handleData', function () { + it('should show a max of 20 dots for full progress', function () { progress.init(1000); progress.progress(1000); progress.complete(); @@ -70,7 +70,7 @@ describe('kibana cli', function() { expect(logger.log.getCall(21).args[0]).toMatch(/complete/i); }); - it('should show dot for each 5% of completion', function() { + it('should show dot for each 5% of completion', function () { progress.init(1000); expect(logger.log.callCount).toBe(1); diff --git a/src/cli_plugin/install/rename.js b/src/cli_plugin/install/rename.js index 92adb213680075..1e5d94d4743753 100644 --- a/src/cli_plugin/install/rename.js +++ b/src/cli_plugin/install/rename.js @@ -21,7 +21,7 @@ import { rename } from 'fs'; import { delay } from 'lodash'; export function renamePlugin(workingPath, finalPath) { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { const start = Date.now(); const retryTime = 3000; const retryDelay = 100; diff --git a/src/cli_plugin/install/rename.test.js b/src/cli_plugin/install/rename.test.js index c725a1218cbd22..40df75adc5efaf 100644 --- a/src/cli_plugin/install/rename.test.js +++ b/src/cli_plugin/install/rename.test.js @@ -22,63 +22,63 @@ import fs from 'fs'; import { renamePlugin } from './rename'; -describe('plugin folder rename', function() { +describe('plugin folder rename', function () { let renameStub; - beforeEach(function() { + beforeEach(function () { renameStub = sinon.stub(); }); - afterEach(function() { + afterEach(function () { fs.rename.restore(); }); - it('should rethrow any exceptions', function() { + it('should rethrow any exceptions', function () { renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb({ code: 'error', }); }); - return renamePlugin('/foo/bar', '/bar/foo').catch(function(err) { + return renamePlugin('/foo/bar', '/bar/foo').catch(function (err) { expect(err.code).toBe('error'); expect(renameStub.callCount).toBe(1); }); }); - it('should resolve if there are no errors', function() { + it('should resolve if there are no errors', function () { renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb(); }); return renamePlugin('/foo/bar', '/bar/foo') - .then(function() { + .then(function () { expect(renameStub.callCount).toBe(1); }) - .catch(function() { + .catch(function () { throw new Error("We shouldn't have any errors"); }); }); - describe('Windows', function() { + describe('Windows', function () { let platform; - beforeEach(function() { + beforeEach(function () { platform = Object.getOwnPropertyDescriptor(process, 'platform'); Object.defineProperty(process, 'platform', { value: 'win32', }); }); - afterEach(function() { + afterEach(function () { Object.defineProperty(process, 'platform', platform); }); - it('should retry on Windows EPERM errors for up to 3 seconds', function() { + it('should retry on Windows EPERM errors for up to 3 seconds', function () { renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb({ code: 'EPERM', }); }); - return renamePlugin('/foo/bar', '/bar/foo').catch(function(err) { + return renamePlugin('/foo/bar', '/bar/foo').catch(function (err) { expect(err.code).toBe('EPERM'); expect(renameStub.callCount).toBeGreaterThan(1); }); diff --git a/src/cli_plugin/install/settings.js b/src/cli_plugin/install/settings.js index 1f924caddf1b7f..40c845fc37a9e6 100644 --- a/src/cli_plugin/install/settings.js +++ b/src/cli_plugin/install/settings.js @@ -56,7 +56,7 @@ export function parse(command, options, kbnPackage) { settings.workingPath = resolve(settings.pluginDir, '.plugin.installing'); settings.tempArchiveFile = resolve(settings.workingPath, 'archive.part'); settings.tempPackageFile = resolve(settings.workingPath, 'package.json'); - settings.setPlugin = function(plugin) { + settings.setPlugin = function (plugin) { settings.plugin = plugin; settings.pluginPath = resolve(settings.pluginDir, settings.plugin.name); }; diff --git a/src/cli_plugin/install/settings.test.js b/src/cli_plugin/install/settings.test.js index 1f0aef4377b40e..39ca07405ade25 100644 --- a/src/cli_plugin/install/settings.test.js +++ b/src/cli_plugin/install/settings.test.js @@ -21,23 +21,23 @@ import { fromRoot } from '../../core/server/utils'; import { resolve } from 'path'; import { parseMilliseconds, parse } from './settings'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('command line option parsing', function() { - describe('parseMilliseconds function', function() { - it('should return 0 for an empty string', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('command line option parsing', function () { + describe('parseMilliseconds function', function () { + it('should return 0 for an empty string', function () { const value = ''; const result = parseMilliseconds(value); expect(result).toBe(0); }); - it('should return 0 for a number with an invalid unit of measure', function() { + it('should return 0 for a number with an invalid unit of measure', function () { const result = parseMilliseconds('1gigablasts'); expect(result).toBe(0); }); - it('should assume a number with no unit of measure is specified as milliseconds', function() { + it('should assume a number with no unit of measure is specified as milliseconds', function () { const result = parseMilliseconds(1); expect(result).toBe(1); @@ -45,53 +45,53 @@ describe('kibana cli', function() { expect(result2).toBe(1); }); - it('should interpret a number with "s" as the unit of measure as seconds', function() { + it('should interpret a number with "s" as the unit of measure as seconds', function () { const result = parseMilliseconds('5s'); expect(result).toBe(5 * 1000); }); - it('should interpret a number with "second" as the unit of measure as seconds', function() { + it('should interpret a number with "second" as the unit of measure as seconds', function () { const result = parseMilliseconds('5second'); expect(result).toBe(5 * 1000); }); - it('should interpret a number with "seconds" as the unit of measure as seconds', function() { + it('should interpret a number with "seconds" as the unit of measure as seconds', function () { const result = parseMilliseconds('5seconds'); expect(result).toBe(5 * 1000); }); - it('should interpret a number with "m" as the unit of measure as minutes', function() { + it('should interpret a number with "m" as the unit of measure as minutes', function () { const result = parseMilliseconds('9m'); expect(result).toBe(9 * 1000 * 60); }); - it('should interpret a number with "minute" as the unit of measure as minutes', function() { + it('should interpret a number with "minute" as the unit of measure as minutes', function () { const result = parseMilliseconds('9minute'); expect(result).toBe(9 * 1000 * 60); }); - it('should interpret a number with "minutes" as the unit of measure as minutes', function() { + it('should interpret a number with "minutes" as the unit of measure as minutes', function () { const result = parseMilliseconds('9minutes'); expect(result).toBe(9 * 1000 * 60); }); }); - describe('parse function', function() { + describe('parse function', function () { const command = 'plugin name'; let options = {}; const kbnPackage = { version: 1234 }; - beforeEach(function() { + beforeEach(function () { options = { pluginDir: fromRoot('plugins') }; }); - describe('timeout option', function() { - it('should default to 0 (milliseconds)', function() { + describe('timeout option', function () { + it('should default to 0 (milliseconds)', function () { const settings = parse(command, options, kbnPackage); expect(settings.timeout).toBe(0); }); - it('should set settings.timeout property', function() { + it('should set settings.timeout property', function () { options.timeout = 1234; const settings = parse(command, options, kbnPackage); @@ -99,14 +99,14 @@ describe('kibana cli', function() { }); }); - describe('quiet option', function() { - it('should default to false', function() { + describe('quiet option', function () { + it('should default to false', function () { const settings = parse(command, options, kbnPackage); expect(settings.quiet).toBe(false); }); - it('should set settings.quiet property to true', function() { + it('should set settings.quiet property to true', function () { options.quiet = true; const settings = parse(command, options, kbnPackage); @@ -114,14 +114,14 @@ describe('kibana cli', function() { }); }); - describe('silent option', function() { - it('should default to false', function() { + describe('silent option', function () { + it('should default to false', function () { const settings = parse(command, options, kbnPackage); expect(settings.silent).toBe(false); }); - it('should set settings.silent property to true', function() { + it('should set settings.silent property to true', function () { options.silent = true; const settings = parse(command, options, kbnPackage); @@ -129,14 +129,14 @@ describe('kibana cli', function() { }); }); - describe('config option', function() { - it('should default to ZLS', function() { + describe('config option', function () { + it('should default to ZLS', function () { const settings = parse(command, options, kbnPackage); expect(settings.config).toBe(''); }); - it('should set settings.config property', function() { + it('should set settings.config property', function () { options.config = 'foo bar baz'; const settings = parse(command, options, kbnPackage); @@ -144,14 +144,14 @@ describe('kibana cli', function() { }); }); - describe('pluginDir option', function() { - it('should default to plugins', function() { + describe('pluginDir option', function () { + it('should default to plugins', function () { const settings = parse(command, options, kbnPackage); expect(settings.pluginDir).toBe(fromRoot('plugins')); }); - it('should set settings.config property', function() { + it('should set settings.config property', function () { options.pluginDir = 'foo bar baz'; const settings = parse(command, options, kbnPackage); @@ -159,16 +159,16 @@ describe('kibana cli', function() { }); }); - describe('command value', function() { - it('should set settings.plugin property', function() { + describe('command value', function () { + it('should set settings.plugin property', function () { const settings = parse(command, options, kbnPackage); expect(settings.plugin).toBe(command); }); }); - describe('urls collection', function() { - it('should populate the settings.urls property', function() { + describe('urls collection', function () { + it('should populate the settings.urls property', function () { const settings = parse(command, options, kbnPackage); const expected = [ @@ -180,8 +180,8 @@ describe('kibana cli', function() { }); }); - describe('workingPath value', function() { - it('should set settings.workingPath property', function() { + describe('workingPath value', function () { + it('should set settings.workingPath property', function () { options.pluginDir = 'foo/bar/baz'; const settings = parse(command, options, kbnPackage); const expected = resolve('foo/bar/baz', '.plugin.installing'); @@ -190,8 +190,8 @@ describe('kibana cli', function() { }); }); - describe('tempArchiveFile value', function() { - it('should set settings.tempArchiveFile property', function() { + describe('tempArchiveFile value', function () { + it('should set settings.tempArchiveFile property', function () { options.pluginDir = 'foo/bar/baz'; const settings = parse(command, options, kbnPackage); const expected = resolve('foo/bar/baz', '.plugin.installing', 'archive.part'); @@ -200,8 +200,8 @@ describe('kibana cli', function() { }); }); - describe('tempPackageFile value', function() { - it('should set settings.tempPackageFile property', function() { + describe('tempPackageFile value', function () { + it('should set settings.tempPackageFile property', function () { options.pluginDir = 'foo/bar/baz'; const settings = parse(command, options, kbnPackage); const expected = resolve('foo/bar/baz', '.plugin.installing', 'package.json'); diff --git a/src/cli_plugin/install/zip.js b/src/cli_plugin/install/zip.js index 03e6edb63b4ff1..52eba2ea239a2c 100644 --- a/src/cli_plugin/install/zip.js +++ b/src/cli_plugin/install/zip.js @@ -34,29 +34,29 @@ export function analyzeArchive(archive) { const regExp = new RegExp('(kibana[\\\\/][^\\\\/]+)[\\\\/]package.json', 'i'); return new Promise((resolve, reject) => { - yauzl.open(archive, { lazyEntries: true }, function(err, zipfile) { + yauzl.open(archive, { lazyEntries: true }, function (err, zipfile) { if (err) { return reject(err); } zipfile.readEntry(); - zipfile.on('entry', function(entry) { + zipfile.on('entry', function (entry) { const match = entry.fileName.match(regExp); if (!match) { return zipfile.readEntry(); } - zipfile.openReadStream(entry, function(err, readable) { + zipfile.openReadStream(entry, function (err, readable) { const chunks = []; if (err) { return reject(err); } - readable.on('data', chunk => chunks.push(chunk)); + readable.on('data', (chunk) => chunks.push(chunk)); - readable.on('end', function() { + readable.on('end', function () { const contents = Buffer.concat(chunks).toString(); const pkg = JSON.parse(contents); @@ -92,14 +92,14 @@ export function _isDirectory(filename) { export function extractArchive(archive, targetDir, extractPath) { return new Promise((resolve, reject) => { - yauzl.open(archive, { lazyEntries: true }, function(err, zipfile) { + yauzl.open(archive, { lazyEntries: true }, function (err, zipfile) { if (err) { return reject(err); } zipfile.readEntry(); zipfile.on('close', resolve); - zipfile.on('entry', function(entry) { + zipfile.on('entry', function (entry) { let fileName = entry.fileName; if (extractPath && fileName.startsWith(extractPath)) { @@ -113,7 +113,7 @@ export function extractArchive(archive, targetDir, extractPath) { } if (_isDirectory(fileName)) { - mkdir(fileName, { recursive: true }, function(err) { + mkdir(fileName, { recursive: true }, function (err) { if (err) { return reject(err); } @@ -122,13 +122,13 @@ export function extractArchive(archive, targetDir, extractPath) { }); } else { // file entry - zipfile.openReadStream(entry, function(err, readStream) { + zipfile.openReadStream(entry, function (err, readStream) { if (err) { return reject(err); } // ensure parent directory exists - mkdir(path.dirname(fileName), { recursive: true }, function(err) { + mkdir(path.dirname(fileName), { recursive: true }, function (err) { if (err) { return reject(err); } @@ -136,7 +136,7 @@ export function extractArchive(archive, targetDir, extractPath) { readStream.pipe( createWriteStream(fileName, { mode: entry.externalFileAttributes >>> 16 }) ); - readStream.on('end', function() { + readStream.on('end', function () { zipfile.readEntry(); }); }); diff --git a/src/cli_plugin/install/zip.test.js b/src/cli_plugin/install/zip.test.js index 8f75367ec8eb47..28367e9e244531 100644 --- a/src/cli_plugin/install/zip.test.js +++ b/src/cli_plugin/install/zip.test.js @@ -24,8 +24,8 @@ import glob from 'glob'; import fs from 'fs'; import { analyzeArchive, extractArchive, _isDirectory } from './zip'; -describe('kibana cli', function() { - describe('zip', function() { +describe('kibana cli', function () { + describe('zip', function () { const repliesPath = path.resolve(__dirname, '__fixtures__', 'replies'); const archivePath = path.resolve(repliesPath, 'test_plugin.zip'); @@ -40,7 +40,7 @@ describe('kibana cli', function() { del.sync(tempPath, { force: true }); }); - describe('analyzeArchive', function() { + describe('analyzeArchive', function () { it('returns array of plugins', async () => { const packages = await analyzeArchive(archivePath); const plugin = packages[0]; diff --git a/src/cli_plugin/lib/log_warnings.js b/src/cli_plugin/lib/log_warnings.js index 3adf0ba849c23d..b4542acecb3050 100644 --- a/src/cli_plugin/lib/log_warnings.js +++ b/src/cli_plugin/lib/log_warnings.js @@ -17,8 +17,8 @@ * under the License. */ -export default function(settings, logger) { - process.on('warning', warning => { +export default function (settings, logger) { + process.on('warning', (warning) => { // deprecation warnings do no reflect a current problem for // the user and therefor should be filtered out. if (warning.name === 'DeprecationWarning') { diff --git a/src/cli_plugin/lib/logger.test.js b/src/cli_plugin/lib/logger.test.js index db8454f465b47a..00cad1a9bbb114 100644 --- a/src/cli_plugin/lib/logger.test.js +++ b/src/cli_plugin/lib/logger.test.js @@ -20,21 +20,21 @@ import sinon from 'sinon'; import Logger from './logger'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('logger', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('logger', function () { let logger; - describe('logger.log', function() { - beforeEach(function() { + describe('logger.log', function () { + beforeEach(function () { sinon.stub(process.stdout, 'write'); }); - afterEach(function() { + afterEach(function () { process.stdout.write.restore(); }); - it('should log messages to the console and append a new line', function() { + it('should log messages to the console and append a new line', function () { logger = new Logger({ silent: false, quiet: false }); const message = 'this is my message'; @@ -45,7 +45,7 @@ describe('kibana cli', function() { expect(process.stdout.write.getCall(callCount - 1).args[0]).toBe('\n'); }); - it('should log messages to the console and append not append a new line', function() { + it('should log messages to the console and append not append a new line', function () { logger = new Logger({ silent: false, quiet: false }); for (let i = 0; i < 10; i++) { logger.log('.', true); @@ -68,7 +68,7 @@ describe('kibana cli', function() { expect(process.stdout.write.getCall(12).args[0]).toBe('\n'); }); - it('should not log any messages when quiet is set', function() { + it('should not log any messages when quiet is set', function () { logger = new Logger({ silent: false, quiet: true }); const message = 'this is my message'; @@ -82,7 +82,7 @@ describe('kibana cli', function() { expect(process.stdout.write.callCount).toBe(0); }); - it('should not log any messages when silent is set', function() { + it('should not log any messages when silent is set', function () { logger = new Logger({ silent: true, quiet: false }); const message = 'this is my message'; @@ -97,16 +97,16 @@ describe('kibana cli', function() { }); }); - describe('logger.error', function() { - beforeEach(function() { + describe('logger.error', function () { + beforeEach(function () { sinon.stub(process.stderr, 'write'); }); - afterEach(function() { + afterEach(function () { process.stderr.write.restore(); }); - it('should log error messages to the console and append a new line', function() { + it('should log error messages to the console and append a new line', function () { logger = new Logger({ silent: false, quiet: false }); const message = 'this is my error'; @@ -114,7 +114,7 @@ describe('kibana cli', function() { expect(process.stderr.write.calledWith(message + '\n')).toBe(true); }); - it('should log error messages to the console when quiet is set', function() { + it('should log error messages to the console when quiet is set', function () { logger = new Logger({ silent: false, quiet: true }); const message = 'this is my error'; @@ -122,7 +122,7 @@ describe('kibana cli', function() { expect(process.stderr.write.calledWith(message + '\n')).toBe(true); }); - it('should not log any error messages when silent is set', function() { + it('should not log any error messages when silent is set', function () { logger = new Logger({ silent: true, quiet: false }); const message = 'this is my error'; diff --git a/src/cli_plugin/list/list.js b/src/cli_plugin/list/list.js index d53e868b32e362..b34631e5dfd085 100644 --- a/src/cli_plugin/list/list.js +++ b/src/cli_plugin/list/list.js @@ -21,7 +21,7 @@ import { statSync, readdirSync, readFileSync } from 'fs'; import { join } from 'path'; export default function list(settings, logger) { - readdirSync(settings.pluginDir).forEach(filename => { + readdirSync(settings.pluginDir).forEach((filename) => { const stat = statSync(join(settings.pluginDir, filename)); if (stat.isDirectory() && filename[0] !== '.') { diff --git a/src/cli_plugin/list/list.test.js b/src/cli_plugin/list/list.test.js index c6480ca52b59a2..071a253fa87fe0 100644 --- a/src/cli_plugin/list/list.test.js +++ b/src/cli_plugin/list/list.test.js @@ -30,8 +30,8 @@ function createPlugin(name, version, pluginBaseDir) { appendFileSync(join(pluginDir, 'package.json'), '{"version": "' + version + '"}'); } -describe('kibana cli', function() { - describe('plugin lister', function() { +describe('kibana cli', function () { + describe('plugin lister', function () { const pluginDir = join(__dirname, '.test.data.list'); let logger; @@ -39,7 +39,7 @@ describe('kibana cli', function() { pluginDir: pluginDir, }; - beforeEach(function() { + beforeEach(function () { logger = new Logger(settings); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); @@ -47,13 +47,13 @@ describe('kibana cli', function() { mkdirSync(pluginDir, { recursive: true }); }); - afterEach(function() { + afterEach(function () { logger.log.restore(); logger.error.restore(); del.sync(pluginDir); }); - it('list all of the folders in the plugin folder', function() { + it('list all of the folders in the plugin folder', function () { createPlugin('plugin1', '5.0.0-alpha2', pluginDir); createPlugin('plugin2', '3.2.1', pluginDir); createPlugin('plugin3', '1.2.3', pluginDir); @@ -65,7 +65,7 @@ describe('kibana cli', function() { expect(logger.log.calledWith('plugin3@1.2.3')).toBe(true); }); - it('ignore folders that start with a period', function() { + it('ignore folders that start with a period', function () { createPlugin('.foo', '1.0.0', pluginDir); createPlugin('plugin1', '5.0.0-alpha2', pluginDir); createPlugin('plugin2', '3.2.1', pluginDir); @@ -78,7 +78,7 @@ describe('kibana cli', function() { expect(logger.log.calledWith('.bar@1.0.0')).toBe(false); }); - it('list should only list folders', function() { + it('list should only list folders', function () { createPlugin('plugin1', '1.0.0', pluginDir); createPlugin('plugin2', '1.0.0', pluginDir); createPlugin('plugin3', '1.0.0', pluginDir); @@ -91,22 +91,22 @@ describe('kibana cli', function() { expect(logger.log.calledWith('plugin3@1.0.0')).toBe(true); }); - it('list should throw an exception if a plugin does not have a package.json', function() { + it('list should throw an exception if a plugin does not have a package.json', function () { createPlugin('plugin1', '1.0.0', pluginDir); mkdirSync(join(pluginDir, 'empty-plugin'), { recursive: true }); - expect(function() { + expect(function () { list(settings, logger); }).toThrowError('Unable to read package.json file for plugin empty-plugin'); }); - it('list should throw an exception if a plugin have an empty package.json', function() { + it('list should throw an exception if a plugin have an empty package.json', function () { createPlugin('plugin1', '1.0.0', pluginDir); const invalidPluginDir = join(pluginDir, 'invalid-plugin'); mkdirSync(invalidPluginDir, { recursive: true }); appendFileSync(join(invalidPluginDir, 'package.json'), ''); - expect(function() { + expect(function () { list(settings, logger); }).toThrowError('Unable to read package.json file for plugin invalid-plugin'); }); diff --git a/src/cli_plugin/list/settings.test.js b/src/cli_plugin/list/settings.test.js index 144b5d8661527e..85e6cb88e82fd7 100644 --- a/src/cli_plugin/list/settings.test.js +++ b/src/cli_plugin/list/settings.test.js @@ -20,24 +20,24 @@ import { fromRoot } from '../../core/server/utils'; import { parse } from './settings'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('command line option parsing', function() { - describe('parse function', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('command line option parsing', function () { + describe('parse function', function () { let command; const options = {}; - beforeEach(function() { + beforeEach(function () { command = { pluginDir: fromRoot('plugins') }; }); - describe('pluginDir option', function() { - it('should default to plugins', function() { + describe('pluginDir option', function () { + it('should default to plugins', function () { const settings = parse(command, options); expect(settings.pluginDir).toBe(fromRoot('plugins')); }); - it('should set settings.config property', function() { + it('should set settings.config property', function () { command.pluginDir = 'foo bar baz'; const settings = parse(command, options); diff --git a/src/cli_plugin/remove/remove.test.js b/src/cli_plugin/remove/remove.test.js index 032a17abe209e6..4bf061820aa050 100644 --- a/src/cli_plugin/remove/remove.test.js +++ b/src/cli_plugin/remove/remove.test.js @@ -25,15 +25,15 @@ import remove from './remove'; import { join } from 'path'; import { writeFileSync, existsSync, mkdirSync } from 'fs'; -describe('kibana cli', function() { - describe('plugin remover', function() { +describe('kibana cli', function () { + describe('plugin remover', function () { const pluginDir = join(__dirname, '.test.data.remove'); let processExitStub; let logger; const settings = { pluginDir }; - beforeEach(function() { + beforeEach(function () { processExitStub = sinon.stub(process, 'exit'); logger = new Logger(settings); sinon.stub(logger, 'log'); @@ -42,14 +42,14 @@ describe('kibana cli', function() { mkdirSync(pluginDir, { recursive: true }); }); - afterEach(function() { + afterEach(function () { processExitStub.restore(); logger.log.restore(); logger.error.restore(); del.sync(pluginDir); }); - it('throw an error if the plugin is not installed.', function() { + it('throw an error if the plugin is not installed.', function () { settings.pluginPath = join(pluginDir, 'foo'); settings.plugin = 'foo'; @@ -58,7 +58,7 @@ describe('kibana cli', function() { expect(process.exit.called).toBe(true); }); - it('throw an error if the specified plugin is not a folder.', function() { + it('throw an error if the specified plugin is not a folder.', function () { writeFileSync(join(pluginDir, 'foo'), 'This is a file, and not a folder.'); remove(settings, logger); @@ -85,7 +85,7 @@ describe('kibana cli', function() { ); }); - it('delete the specified folder.', function() { + it('delete the specified folder.', function () { settings.pluginPath = join(pluginDir, 'foo'); mkdirSync(join(pluginDir, 'foo'), { recursive: true }); mkdirSync(join(pluginDir, 'bar'), { recursive: true }); diff --git a/src/cli_plugin/remove/settings.test.js b/src/cli_plugin/remove/settings.test.js index 5bb4b30cfff095..b3110e1ff0499a 100644 --- a/src/cli_plugin/remove/settings.test.js +++ b/src/cli_plugin/remove/settings.test.js @@ -20,25 +20,25 @@ import { fromRoot } from '../../core/server/utils'; import { parse } from './settings'; -describe('kibana cli', function() { - describe('plugin installer', function() { - describe('command line option parsing', function() { - describe('parse function', function() { +describe('kibana cli', function () { + describe('plugin installer', function () { + describe('command line option parsing', function () { + describe('parse function', function () { const command = 'plugin name'; let options = {}; const kbnPackage = { version: 1234 }; - beforeEach(function() { + beforeEach(function () { options = { pluginDir: fromRoot('plugins') }; }); - describe('quiet option', function() { - it('should default to false', function() { + describe('quiet option', function () { + it('should default to false', function () { const settings = parse(command, options, kbnPackage); expect(settings.quiet).toBe(false); }); - it('should set settings.quiet property to true', function() { + it('should set settings.quiet property to true', function () { options.quiet = true; const settings = parse(command, options, kbnPackage); @@ -46,14 +46,14 @@ describe('kibana cli', function() { }); }); - describe('silent option', function() { - it('should default to false', function() { + describe('silent option', function () { + it('should default to false', function () { const settings = parse(command, options, kbnPackage); expect(settings.silent).toBe(false); }); - it('should set settings.silent property to true', function() { + it('should set settings.silent property to true', function () { options.silent = true; const settings = parse(command, options, kbnPackage); @@ -61,14 +61,14 @@ describe('kibana cli', function() { }); }); - describe('config option', function() { - it('should default to ZLS', function() { + describe('config option', function () { + it('should default to ZLS', function () { const settings = parse(command, options, kbnPackage); expect(settings.config).toBe(''); }); - it('should set settings.config property', function() { + it('should set settings.config property', function () { options.config = 'foo bar baz'; const settings = parse(command, options, kbnPackage); @@ -76,14 +76,14 @@ describe('kibana cli', function() { }); }); - describe('pluginDir option', function() { - it('should default to plugins', function() { + describe('pluginDir option', function () { + it('should default to plugins', function () { const settings = parse(command, options, kbnPackage); expect(settings.pluginDir).toBe(fromRoot('plugins')); }); - it('should set settings.config property', function() { + it('should set settings.config property', function () { options.pluginDir = 'foo bar baz'; const settings = parse(command, options, kbnPackage); @@ -91,8 +91,8 @@ describe('kibana cli', function() { }); }); - describe('command value', function() { - it('should set settings.plugin property', function() { + describe('command value', function () { + it('should set settings.plugin property', function () { const settings = parse(command, options, kbnPackage); expect(settings.plugin).toBe(command); diff --git a/src/core/CONVENTIONS.md b/src/core/CONVENTIONS.md index c1241695803376..447c6f396945f4 100644 --- a/src/core/CONVENTIONS.md +++ b/src/core/CONVENTIONS.md @@ -68,7 +68,7 @@ my_plugin/    ├── index.ts    └── plugin.ts ``` -- [Manifest file](/docs/development/core/server/kibana-plugin-server.pluginmanifest.md) should be defined on top level. +- [Manifest file](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) should be defined on top level. - Both `server` and `public` should have an `index.ts` and a `plugin.ts` file: - `index.ts` should only contain: - The `plugin` export diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 02d46b1583b592..ce2d652257e1f0 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1240,6 +1240,7 @@ import { npStart: { plugins } } from 'ui/new_platform'; | `ui/filter_manager` | `plugins.data.filter` | -- | | `ui/index_patterns` | `plugins.data.indexPatterns` | | `import 'ui/management'` | `plugins.management.sections` | | +| `import 'ui/registry/field_format_editors'` | `plugins.indexPatternManagement.fieldFormatEditors` | | | `ui/registry/field_formats` | `plugins.data.fieldFormats` | | | `ui/registry/feature_catalogue` | `plugins.home.featureCatalogue.register` | Must add `home` as a dependency in your kibana.json. | | `ui/registry/vis_types` | `plugins.visualizations` | -- | diff --git a/src/core/MIGRATION_EXAMPLES.md b/src/core/MIGRATION_EXAMPLES.md index c91c00bc1aa021..5cec20fb900f26 100644 --- a/src/core/MIGRATION_EXAMPLES.md +++ b/src/core/MIGRATION_EXAMPLES.md @@ -6,6 +6,7 @@ APIs to their New Platform equivalents. - [Migration Examples](#migration-examples) - [Configuration](#configuration) - [Declaring config schema](#declaring-config-schema) + - [Using New Platform config in a new plugin](#using-new-platform-config-in-a-new-plugin) - [Using New Platform config from a Legacy plugin](#using-new-platform-config-from-a-legacy-plugin) - [Create a New Platform plugin](#create-a-new-platform-plugin) - [HTTP Routes](#http-routes) @@ -15,11 +16,16 @@ APIs to their New Platform equivalents. - [4. New Platform plugin](#4-new-platform-plugin) - [Accessing Services](#accessing-services) - [Migrating Hapi "pre" handlers](#migrating-hapi-pre-handlers) + - [Simple example](#simple-example) + - [Full Example](#full-example) - [Chrome](#chrome) - - [Updating an application navlink](#updating-application-navlink) + - [Updating an application navlink](#updating-an-application-navlink) - [Chromeless Applications](#chromeless-applications) - [Render HTML Content](#render-html-content) - [Saved Objects types](#saved-objects-types) + - [Concrete example](#concrete-example) + - [Changes in structure compared to legacy](#changes-in-structure-compared-to-legacy) + - [Remarks](#remarks) - [UiSettings](#uisettings) ## Configuration @@ -65,7 +71,7 @@ export type MyPluginConfig = TypeOf; ### Using New Platform config in a new plugin After setting the config schema for your plugin, you might want to reach the configuration in the plugin. -It is provided as part of the [PluginInitializerContext](../../docs/development/core/server/kibana-plugin-server.plugininitializercontext.md) +It is provided as part of the [PluginInitializerContext](../../docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.md) in the *constructor* of the plugin: ```ts @@ -210,9 +216,9 @@ new kibana.Plugin({ In the legacy platform, plugins have direct access to the Hapi `server` object which gives full access to all of Hapi's API. In the New Platform, plugins have access to the -[HttpServiceSetup](/docs/development/core/server/kibana-plugin-server.httpservicesetup.md) +[HttpServiceSetup](/docs/development/core/server/kibana-plugin-core-server.httpservicesetup.md) interface, which is exposed via the -[CoreSetup](/docs/development/core/server/kibana-plugin-server.coresetup.md) +[CoreSetup](/docs/development/core/server/kibana-plugin-core-server.coresetup.md) object injected into the `setup` method of server-side plugins. This interface has a different API with slightly different behaviors. @@ -415,7 +421,7 @@ Services in the Legacy Platform were typically available via methods on either `server.plugins.*`, `server.*`, or `req.*`. In the New Platform, all services are available via the `context` argument to the route handler. The type of this argument is the -[RequestHandlerContext](/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md). +[RequestHandlerContext](/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md). The APIs available here will include all Core services and any services registered by plugins this plugin depends on. diff --git a/src/core/public/application/application_leave.test.ts b/src/core/public/application/application_leave.test.ts index e06183d8bb8d96..b560bbc0cbc25e 100644 --- a/src/core/public/application/application_leave.test.ts +++ b/src/core/public/application/application_leave.test.ts @@ -31,16 +31,16 @@ describe('isConfirmAction', () => { describe('getLeaveAction', () => { it('returns the default action provided by the handler', () => { - expect(getLeaveAction(actions => actions.default())).toEqual({ + expect(getLeaveAction((actions) => actions.default())).toEqual({ type: AppLeaveActionType.default, }); }); it('returns the confirm action provided by the handler', () => { - expect(getLeaveAction(actions => actions.confirm('some message'))).toEqual({ + expect(getLeaveAction((actions) => actions.confirm('some message'))).toEqual({ type: AppLeaveActionType.confirm, text: 'some message', }); - expect(getLeaveAction(actions => actions.confirm('another message', 'a title'))).toEqual({ + expect(getLeaveAction((actions) => actions.confirm('another message', 'a title'))).toEqual({ type: AppLeaveActionType.confirm, text: 'another message', title: 'a title', diff --git a/src/core/public/application/application_service.mock.ts b/src/core/public/application/application_service.mock.ts index d2a827d381be54..24c0e66359afa5 100644 --- a/src/core/public/application/application_service.mock.ts +++ b/src/core/public/application/application_service.mock.ts @@ -50,6 +50,7 @@ const createStartContractMock = (): jest.Mocked => { currentAppId$: currentAppId$.asObservable(), capabilities: capabilitiesServiceMock.createStartContract().capabilities, navigateToApp: jest.fn(), + navigateToUrl: jest.fn(), getUrlForApp: jest.fn(), registerMountContext: jest.fn(), }; @@ -64,7 +65,8 @@ const createInternalStartContractMock = (): jest.Mocked currentAppId$.next(appId)), + navigateToApp: jest.fn().mockImplementation((appId) => currentAppId$.next(appId)), + navigateToUrl: jest.fn(), registerMountContext: jest.fn(), }; }; diff --git a/src/core/public/application/application_service.test.mocks.ts b/src/core/public/application/application_service.test.mocks.ts index d829cf18e56be2..a096f052097084 100644 --- a/src/core/public/application/application_service.test.mocks.ts +++ b/src/core/public/application/application_service.test.mocks.ts @@ -34,3 +34,9 @@ export const createBrowserHistoryMock = jest.fn().mockReturnValue(MockHistory); jest.doMock('history', () => ({ createBrowserHistory: createBrowserHistoryMock, })); + +export const parseAppUrlMock = jest.fn(); +jest.doMock('./utils', () => ({ + ...jest.requireActual('./utils'), + parseAppUrl: parseAppUrlMock, +})); diff --git a/src/core/public/application/application_service.test.ts b/src/core/public/application/application_service.test.ts index 04ff844ffc1505..b65a8581e5b588 100644 --- a/src/core/public/application/application_service.test.ts +++ b/src/core/public/application/application_service.test.ts @@ -17,6 +17,12 @@ * under the License. */ +import { + MockCapabilitiesService, + MockHistory, + parseAppUrlMock, +} from './application_service.test.mocks'; + import { createElement } from 'react'; import { BehaviorSubject, Subject } from 'rxjs'; import { bufferCount, take, takeUntil } from 'rxjs/operators'; @@ -26,7 +32,6 @@ import { injectedMetadataServiceMock } from '../injected_metadata/injected_metad import { contextServiceMock } from '../context/context_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; import { overlayServiceMock } from '../overlays/overlay_service.mock'; -import { MockCapabilitiesService, MockHistory } from './application_service.test.mocks'; import { MockLifecycle } from './test_types'; import { ApplicationService } from './application_service'; import { App, AppNavLinkStatus, AppStatus, AppUpdater, LegacyApp } from './types'; @@ -61,6 +66,7 @@ describe('#setup()', () => { http, context: contextServiceMock.createSetupContract(), injectedMetadata: injectedMetadataServiceMock.createSetupContract(), + redirectTo: jest.fn(), }; setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(false); startDeps = { http, overlays: overlayServiceMock.createStartContract() }; @@ -92,7 +98,7 @@ describe('#setup()', () => { const setup = service.setup(setupDeps); const pluginId = Symbol('plugin'); - const updater$ = new BehaviorSubject(app => ({})); + const updater$ = new BehaviorSubject((app) => ({})); setup.register(pluginId, createApp({ id: 'app1', updater$ })); setup.register(pluginId, createApp({ id: 'app2' })); const { applications$ } = await service.start(startDeps); @@ -116,7 +122,7 @@ describe('#setup()', () => { }) ); - updater$.next(app => ({ + updater$.next((app) => ({ status: AppStatus.inaccessible, tooltip: 'App inaccessible due to reason', defaultPath: 'foo/bar', @@ -174,6 +180,10 @@ describe('#setup()', () => { ).toThrowErrorMatchingInlineSnapshot( `"Cannot register an application route that includes HTTP base path"` ); + + expect(() => + register(Symbol(), createApp({ id: 'app3', appRoute: '/base-path-i-am-not' })) + ).not.toThrow(); }); }); @@ -220,7 +230,7 @@ describe('#setup()', () => { setup.register(pluginId, createApp({ id: 'app1' })); setup.register(pluginId, createApp({ id: 'app2' })); setup.registerAppUpdater( - new BehaviorSubject(app => { + new BehaviorSubject((app) => { if (app.id === 'app1') { return { status: AppStatus.inaccessible, @@ -260,7 +270,7 @@ describe('#setup()', () => { it(`properly combine with application's updater$`, async () => { const setup = service.setup(setupDeps); const pluginId = Symbol('plugin'); - const appStatusUpdater$ = new BehaviorSubject(app => ({ + const appStatusUpdater$ = new BehaviorSubject((app) => ({ status: AppStatus.inaccessible, navLinkStatus: AppNavLinkStatus.disabled, })); @@ -268,7 +278,7 @@ describe('#setup()', () => { setup.register(pluginId, createApp({ id: 'app2' })); setup.registerAppUpdater( - new BehaviorSubject(app => { + new BehaviorSubject((app) => { if (app.id === 'app1') { return { status: AppStatus.accessible, @@ -311,7 +321,7 @@ describe('#setup()', () => { const pluginId = Symbol('plugin'); setup.register(pluginId, createApp({ id: 'app1' })); setup.registerAppUpdater( - new BehaviorSubject(app => { + new BehaviorSubject((app) => { return { status: AppStatus.inaccessible, navLinkStatus: AppNavLinkStatus.disabled, @@ -319,7 +329,7 @@ describe('#setup()', () => { }) ); setup.registerAppUpdater( - new BehaviorSubject(app => { + new BehaviorSubject((app) => { return { status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.default, @@ -347,7 +357,7 @@ describe('#setup()', () => { const pluginId = Symbol('plugin'); setup.register(pluginId, createApp({ id: 'app1' })); - const statusUpdater = new BehaviorSubject(app => { + const statusUpdater = new BehaviorSubject((app) => { return { status: AppStatus.inaccessible, navLinkStatus: AppNavLinkStatus.disabled, @@ -357,7 +367,7 @@ describe('#setup()', () => { const start = await service.start(startDeps); let latestValue: ReadonlyMap = new Map(); - start.applications$.subscribe(apps => { + start.applications$.subscribe((apps) => { latestValue = apps; }); @@ -370,7 +380,7 @@ describe('#setup()', () => { }) ); - statusUpdater.next(app => { + statusUpdater.next((app) => { return { status: AppStatus.accessible, navLinkStatus: AppNavLinkStatus.hidden, @@ -393,7 +403,7 @@ describe('#setup()', () => { setup.registerLegacyApp(createLegacyApp({ id: 'app1' })); setup.registerAppUpdater( - new BehaviorSubject(app => { + new BehaviorSubject((app) => { return { status: AppStatus.inaccessible, navLinkStatus: AppNavLinkStatus.hidden, @@ -423,7 +433,7 @@ describe('#setup()', () => { const pluginId = Symbol('plugin'); setup.register(pluginId, createApp({ id: 'app1' })); - const updater = new BehaviorSubject(app => ({})); + const updater = new BehaviorSubject((app) => ({})); setup.registerAppUpdater(updater); const start = await service.start(startDeps); @@ -431,17 +441,17 @@ describe('#setup()', () => { expect(MockHistory.push).toHaveBeenCalledWith('/app/app1', undefined); MockHistory.push.mockClear(); - updater.next(app => ({ defaultPath: 'default-path' })); + updater.next((app) => ({ defaultPath: 'default-path' })); await start.navigateToApp('app1'); expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/default-path', undefined); MockHistory.push.mockClear(); - updater.next(app => ({ defaultPath: 'another-path' })); + updater.next((app) => ({ defaultPath: 'another-path' })); await start.navigateToApp('app1'); expect(MockHistory.push).toHaveBeenCalledWith('/app/app1/another-path', undefined); MockHistory.push.mockClear(); - updater.next(app => ({})); + updater.next((app) => ({})); await start.navigateToApp('app1'); expect(MockHistory.push).toHaveBeenCalledWith('/app/app1', undefined); MockHistory.push.mockClear(); @@ -462,12 +472,14 @@ describe('#setup()', () => { describe('#start()', () => { beforeEach(() => { MockHistory.push.mockReset(); + parseAppUrlMock.mockReset(); const http = httpServiceMock.createSetupContract({ basePath: '/base-path' }); setupDeps = { http, context: contextServiceMock.createSetupContract(), injectedMetadata: injectedMetadataServiceMock.createSetupContract(), + redirectTo: jest.fn(), }; setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(false); startDeps = { http, overlays: overlayServiceMock.createStartContract() }; @@ -775,7 +787,6 @@ describe('#start()', () => { }); it('redirects when in legacyMode', async () => { - setupDeps.redirectTo = jest.fn(); setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(true); service.setup(setupDeps); @@ -816,11 +827,11 @@ describe('#start()', () => { const history = createMemoryHistory(); setupDeps.history = history; - const flushPromises = () => new Promise(resolve => setImmediate(resolve)); + const flushPromises = () => new Promise((resolve) => setImmediate(resolve)); // Create an app and a promise that allows us to control when the app completes mounting const createWaitingApp = (props: Partial): [App, () => void] => { let finishMount: () => void; - const mountPromise = new Promise(resolve => (finishMount = resolve)); + const mountPromise = new Promise((resolve) => (finishMount = resolve)); const app = { id: 'some-id', title: 'some-title', @@ -881,7 +892,6 @@ describe('#start()', () => { it('sets window.location.href when navigating to legacy apps', async () => { setupDeps.http = httpServiceMock.createSetupContract({ basePath: '/test' }); setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(true); - setupDeps.redirectTo = jest.fn(); service.setup(setupDeps); const { navigateToApp } = await service.start(startDeps); @@ -893,7 +903,6 @@ describe('#start()', () => { it('handles legacy apps with subapps', async () => { setupDeps.http = httpServiceMock.createSetupContract({ basePath: '/test' }); setupDeps.injectedMetadata.getLegacyMode.mockReturnValue(true); - setupDeps.redirectTo = jest.fn(); const { registerLegacyApp } = service.setup(setupDeps); @@ -905,6 +914,30 @@ describe('#start()', () => { expect(setupDeps.redirectTo).toHaveBeenCalledWith('/test/app/baseApp'); }); }); + + describe('navigateToUrl', () => { + it('calls `redirectTo` when the url is not parseable', async () => { + parseAppUrlMock.mockReturnValue(undefined); + service.setup(setupDeps); + const { navigateToUrl } = await service.start(startDeps); + + await navigateToUrl('/not-an-app-path'); + + expect(MockHistory.push).not.toHaveBeenCalled(); + expect(setupDeps.redirectTo).toHaveBeenCalledWith('/not-an-app-path'); + }); + + it('calls `navigateToApp` when the url is an internal app link', async () => { + parseAppUrlMock.mockReturnValue({ app: 'foo', path: '/some-path' }); + service.setup(setupDeps); + const { navigateToUrl } = await service.start(startDeps); + + await navigateToUrl('/an-app-path'); + + expect(MockHistory.push).toHaveBeenCalledWith('/app/foo/some-path', undefined); + expect(setupDeps.redirectTo).not.toHaveBeenCalled(); + }); + }); }); describe('#stop()', () => { diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 6802c2363b9f80..b52b4984fb5e12 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -46,17 +46,14 @@ import { Mounter, } from './types'; import { getLeaveAction, isConfirmAction } from './application_leave'; -import { appendAppPath } from './utils'; +import { appendAppPath, parseAppUrl, relativeToAbsolute } from './utils'; interface SetupDeps { context: ContextSetup; http: HttpSetup; injectedMetadata: InjectedMetadataSetup; history?: History; - /** - * Only necessary for redirecting to legacy apps - * @deprecated - */ + /** Used to redirect to external urls (and legacy apps) */ redirectTo?: (path: string) => void; } @@ -109,6 +106,7 @@ export class ApplicationService { private history?: History; private mountContext?: IContextContainer; private navigate?: (url: string, state: any) => void; + private redirectTo?: (url: string) => void; public setup({ context, @@ -131,12 +129,12 @@ export class ApplicationService { this.navigate = (url, state) => // basePath not needed here because `history` is configured with basename this.history ? this.history.push(url, state) : redirectTo(basePath.prepend(url)); - + this.redirectTo = redirectTo; this.mountContext = context.createContextContainer(); const registerStatusUpdater = (application: string, updater$: Observable) => { const updaterId = Symbol(); - const subscription = updater$.subscribe(updater => { + const subscription = updater$.subscribe((updater) => { const nextValue = new Map(this.statusUpdaters$.getValue()); nextValue.set(updaterId, { application, @@ -160,7 +158,7 @@ export class ApplicationService { } else { handler = app.mount; } - return async params => { + return async (params) => { this.currentAppId$.next(app.id); return handler(params); }; @@ -179,7 +177,7 @@ export class ApplicationService { throw new Error( `An application is already registered with the appRoute "${app.appRoute}"` ); - } else if (basename && app.appRoute!.startsWith(basename)) { + } else if (basename && app.appRoute!.startsWith(`${basename}/`)) { throw new Error('Cannot register an application route that includes HTTP base path'); } @@ -201,14 +199,14 @@ export class ApplicationService { legacy: false, }); }, - registerLegacyApp: app => { + registerLegacyApp: (app) => { const appRoute = `/app/${app.id.split(':')[0]}`; if (this.registrationClosed) { throw new Error('Applications cannot be registered after "setup"'); } else if (this.apps.has(app.id)) { throw new Error(`An application is already registered with the id "${app.id}"`); - } else if (basename && appRoute!.startsWith(basename)) { + } else if (basename && appRoute!.startsWith(`${basename}/`)) { throw new Error('Cannot register an application route that includes HTTP base path'); } @@ -262,7 +260,7 @@ export class ApplicationService { const applications$ = new BehaviorSubject(availableApps); this.statusUpdaters$ .pipe( - map(statusUpdaters => { + map((statusUpdaters) => { return new Map( [...availableApps].map(([id, app]) => [ id, @@ -271,18 +269,32 @@ export class ApplicationService { ); }) ) - .subscribe(apps => applications$.next(apps)); + .subscribe((apps) => applications$.next(apps)); const applicationStatuses$ = applications$.pipe( - map(apps => new Map([...apps.entries()].map(([id, app]) => [id, app.status!]))), + map((apps) => new Map([...apps.entries()].map(([id, app]) => [id, app.status!]))), shareReplay(1) ); + const navigateToApp: InternalApplicationStart['navigateToApp'] = async ( + appId, + { path, state }: { path?: string; state?: any } = {} + ) => { + if (await this.shouldNavigate(overlays)) { + if (path === undefined) { + path = applications$.value.get(appId)?.defaultPath; + } + this.appLeaveHandlers.delete(this.currentAppId$.value!); + this.navigate!(getAppUrl(availableMounters, appId, path), state); + this.currentAppId$.next(appId); + } + }; + return { applications$, capabilities, currentAppId$: this.currentAppId$.pipe( - filter(appId => appId !== undefined), + filter((appId) => appId !== undefined), distinctUntilChanged(), takeUntil(this.stop$) ), @@ -294,14 +306,13 @@ export class ApplicationService { const relUrl = http.basePath.prepend(getAppUrl(availableMounters, appId, path)); return absolute ? relativeToAbsolute(relUrl) : relUrl; }, - navigateToApp: async (appId, { path, state }: { path?: string; state?: any } = {}) => { - if (await this.shouldNavigate(overlays)) { - if (path === undefined) { - path = applications$.value.get(appId)?.defaultPath; - } - this.appLeaveHandlers.delete(this.currentAppId$.value!); - this.navigate!(getAppUrl(availableMounters, appId, path), state); - this.currentAppId$.next(appId); + navigateToApp, + navigateToUrl: async (url) => { + const appInfo = parseAppUrl(url, http.basePath, this.apps); + if (appInfo) { + return navigateToApp(appInfo.app, { path: appInfo.path }); + } else { + return this.redirectTo!(url); } }, getComponent: () => { @@ -314,7 +325,7 @@ export class ApplicationService { mounters={availableMounters} appStatuses$={applicationStatuses$} setAppLeaveHandler={this.setAppLeaveHandler} - setIsMounting={isMounting => httpLoadingCount$.next(isMounting ? 1 : 0)} + setIsMounting={(isMounting) => httpLoadingCount$.next(isMounting ? 1 : 0)} /> ); }, @@ -360,14 +371,14 @@ export class ApplicationService { this.stop$.next(); this.currentAppId$.complete(); this.statusUpdaters$.complete(); - this.subscriptions.forEach(sub => sub.unsubscribe()); + this.subscriptions.forEach((sub) => sub.unsubscribe()); window.removeEventListener('beforeunload', this.onBeforeUnload); } } const updateStatus = (app: T, statusUpdaters: AppUpdaterWrapper[]): T => { let changes: Partial = {}; - statusUpdaters.forEach(wrapper => { + statusUpdaters.forEach((wrapper) => { if (wrapper.application !== allApplicationsFilter && wrapper.application !== app.id) { return; } @@ -388,10 +399,3 @@ const updateStatus = (app: T, statusUpdaters: AppUpdaterWrapp ...changes, }; }; - -function relativeToAbsolute(url: string) { - // convert all link urls to absolute urls - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -} diff --git a/src/core/public/application/integration_tests/application_service.test.tsx b/src/core/public/application/integration_tests/application_service.test.tsx index e399fbc726977a..89f90a9899dda8 100644 --- a/src/core/public/application/integration_tests/application_service.test.tsx +++ b/src/core/public/application/integration_tests/application_service.test.tsx @@ -31,7 +31,7 @@ import { overlayServiceMock } from '../../overlays/overlay_service.mock'; import { AppMountParameters } from '../types'; import { ScopedHistory } from '../scoped_history'; -const flushPromises = () => new Promise(resolve => setImmediate(resolve)); +const flushPromises = () => new Promise((resolve) => setImmediate(resolve)); describe('ApplicationService', () => { let setupDeps: MockLifecycle<'setup'>; @@ -68,7 +68,7 @@ describe('ApplicationService', () => { const { register } = service.setup(setupDeps); let resolveMount: () => void; - const promise = new Promise(resolve => { + const promise = new Promise((resolve) => { resolveMount = resolve; }); @@ -102,7 +102,7 @@ describe('ApplicationService', () => { const { register } = service.setup(setupDeps); let resolveMount: () => void; - const promise = new Promise(resolve => { + const promise = new Promise((resolve) => { resolveMount = resolve; }); @@ -146,7 +146,7 @@ describe('ApplicationService', () => { id: 'app1', title: 'App1', mount: ({ onAppLeave }: AppMountParameters) => { - onAppLeave(actions => actions.default()); + onAppLeave((actions) => actions.default()); return () => undefined; }, }); @@ -178,7 +178,7 @@ describe('ApplicationService', () => { id: 'app1', title: 'App1', mount: ({ onAppLeave }: AppMountParameters) => { - onAppLeave(actions => actions.default()); + onAppLeave((actions) => actions.default()); return () => undefined; }, }); @@ -213,7 +213,7 @@ describe('ApplicationService', () => { id: 'app1', title: 'App1', mount: ({ onAppLeave }: AppMountParameters) => { - onAppLeave(actions => actions.confirm('confirmation-message', 'confirmation-title')); + onAppLeave((actions) => actions.confirm('confirmation-message', 'confirmation-title')); return () => undefined; }, }); @@ -252,7 +252,7 @@ describe('ApplicationService', () => { id: 'app1', title: 'App1', mount: ({ onAppLeave }: AppMountParameters) => { - onAppLeave(actions => actions.confirm('confirmation-message', 'confirmation-title')); + onAppLeave((actions) => actions.confirm('confirmation-message', 'confirmation-title')); return () => undefined; }, }); diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index 9f379859dc34ff..2827b93f6d17e5 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -45,7 +45,7 @@ describe('AppRouter', () => { const mountersToAppStatus$ = () => { return new BehaviorSubject( new Map( - [...mounters.keys()].map(id => [ + [...mounters.keys()].map((id) => [ id, id.startsWith('disabled') ? AppStatus.inaccessible : AppStatus.accessible, ]) diff --git a/src/core/public/application/integration_tests/utils.tsx b/src/core/public/application/integration_tests/utils.tsx index 6c1b81a26d63c5..8590fb3c820ef7 100644 --- a/src/core/public/application/integration_tests/utils.tsx +++ b/src/core/public/application/integration_tests/utils.tsx @@ -33,7 +33,7 @@ export const createRenderer = (element: ReactElement | null): Renderer => { const dom: Dom = element && mount({element}); return () => - new Promise(async resolve => { + new Promise(async (resolve) => { if (dom) { await act(async () => { dom.update(); diff --git a/src/core/public/application/scoped_history.test.ts b/src/core/public/application/scoped_history.test.ts index a56cffef1e2f27..2b217e54228c2c 100644 --- a/src/core/public/application/scoped_history.test.ts +++ b/src/core/public/application/scoped_history.test.ts @@ -217,7 +217,7 @@ describe('ScopedHistory', () => { gh.push('/app/wow'); const h = new ScopedHistory(gh, '/app/wow'); const listenPaths: string[] = []; - h.listen(l => listenPaths.push(l.pathname)); + h.listen((l) => listenPaths.push(l.pathname)); h.push('/first-page'); h.push('/second-page'); h.push('/third-page'); @@ -237,7 +237,7 @@ describe('ScopedHistory', () => { gh.push('/app/wow'); const h = new ScopedHistory(gh, '/app/wow'); const listenPaths: string[] = []; - const unlisten = h.listen(l => listenPaths.push(l.pathname)); + const unlisten = h.listen((l) => listenPaths.push(l.pathname)); h.push('/first-page'); unlisten(); h.push('/second-page'); @@ -252,7 +252,7 @@ describe('ScopedHistory', () => { gh.push('/app/wow'); const h = new ScopedHistory(gh, '/app/wow'); const listenPaths: string[] = []; - h.listen(l => listenPaths.push(l.pathname)); + h.listen((l) => listenPaths.push(l.pathname)); h.push('/first-page'); gh.push('/app/other'); gh.push('/second-page'); diff --git a/src/core/public/application/scoped_history.ts b/src/core/public/application/scoped_history.ts index 9fa8f0b7f81481..1a7fafa5d85c44 100644 --- a/src/core/public/application/scoped_history.ts +++ b/src/core/public/application/scoped_history.ts @@ -324,7 +324,7 @@ export class ScopedHistory throw new Error(`Unrecognized history action: ${action}`); } - [...this.listeners].forEach(listener => { + [...this.listeners].forEach((listener) => { listener(this.stripBasePath(location), action); }); }); diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 786d11a5ced7f0..c07d929fc5ceaf 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -659,12 +659,41 @@ export interface ApplicationStart { */ navigateToApp(appId: string, options?: { path?: string; state?: any }): Promise; + /** + * Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible. + * + * If all these criteria are true for the given url: + * - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location + * - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) + * - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) + * + * Then a SPA navigation will be performed using `navigateToApp` using the corresponding application and path. + * Otherwise, fallback to a full page reload to navigate to the url using `window.location.assign` + * + * @example + * ```ts + * // current url: `https://kibana:8080/base-path/s/my-space/app/dashboard` + * + * // will call `application.navigateToApp('discover', { path: '/some-path?foo=bar'})` + * application.navigateToUrl('https://kibana:8080/base-path/s/my-space/app/discover/some-path?foo=bar') + * application.navigateToUrl('/base-path/s/my-space/app/discover/some-path?foo=bar') + * + * // will perform a full page reload using `window.location.assign` + * application.navigateToUrl('https://elsewhere:8080/base-path/s/my-space/app/discover/some-path') // origin does not match + * application.navigateToUrl('/app/discover/some-path') // does not include the current basePath + * application.navigateToUrl('/base-path/s/my-space/app/unknown-app/some-path') // unknown application + * ``` + * + * @param url - an absolute url, or a relative path, to navigate to. + */ + navigateToUrl(url: string): Promise; + /** * Returns an URL to a given app, including the global base path. * By default, the URL is relative (/basePath/app/my-app). * Use the `absolute` option to generate an absolute url (http://host:port/basePath/app/my-app) * - * Note that when generating absolute urls, the protocol, host and port are determined from the browser location. + * Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. * * @param appId * @param options.path - optional path inside application to deep link to @@ -677,7 +706,6 @@ export interface ApplicationStart { * plugin that registered this context. Deprecated, use {@link CoreSetup.getStartServices}. * * @deprecated - * @param pluginOpaqueId - The opaque ID of the plugin that is registering the context. * @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to. * @param provider - A {@link IContextProvider} function */ @@ -696,7 +724,7 @@ export interface ApplicationStart { export interface InternalApplicationStart extends Pick< ApplicationStart, - 'capabilities' | 'navigateToApp' | 'getUrlForApp' | 'currentAppId$' + 'capabilities' | 'navigateToApp' | 'navigateToUrl' | 'getUrlForApp' | 'currentAppId$' > { /** * Apps available based on the current capabilities. diff --git a/src/core/public/application/ui/app_container.test.tsx b/src/core/public/application/ui/app_container.test.tsx index 5d573d47bd4203..229354a014103b 100644 --- a/src/core/public/application/ui/app_container.test.tsx +++ b/src/core/public/application/ui/app_container.test.tsx @@ -37,14 +37,14 @@ describe('AppContainer', () => { }); const flushPromises = async () => { - await new Promise(async resolve => { + await new Promise(async (resolve) => { setImmediate(() => resolve()); }); }; const createResolver = (): [Promise, () => void] => { let resolve: () => void | undefined; - const promise = new Promise(r => { + const promise = new Promise((r) => { resolve = r; }); return [promise, resolve!]; diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index aad7e6dcf270a7..332c31c64b6ba1 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -83,10 +83,12 @@ export const AppContainer: FunctionComponent = ({ appBasePath: mounter.appBasePath, history: createScopedHistory(appPath), element: elementRef.current!, - onAppLeave: handler => setAppLeaveHandler(appId, handler), + onAppLeave: (handler) => setAppLeaveHandler(appId, handler), })) || null; } catch (e) { // TODO: add error UI + // eslint-disable-next-line no-console + console.error(e); } finally { setShowSpinner(false); setIsMounting(false); diff --git a/src/core/public/application/utils.test.ts b/src/core/public/application/utils.test.ts index 7ed0919f88c614..a86a1206fc983a 100644 --- a/src/core/public/application/utils.test.ts +++ b/src/core/public/application/utils.test.ts @@ -17,7 +17,15 @@ * under the License. */ -import { removeSlashes, appendAppPath } from './utils'; +import { LegacyApp, App } from './types'; +import { BasePath } from '../http/base_path'; +import { + removeSlashes, + appendAppPath, + isLegacyApp, + relativeToAbsolute, + parseAppUrl, +} from './utils'; describe('removeSlashes', () => { it('only removes duplicates by default', () => { @@ -69,3 +77,385 @@ describe('appendAppPath', () => { expect(appendAppPath('/app/my-app', '/some-path#/hash')).toEqual('/app/my-app/some-path#/hash'); }); }); + +describe('isLegacyApp', () => { + it('returns true for legacy apps', () => { + expect( + isLegacyApp({ + id: 'legacy', + title: 'Legacy App', + appUrl: '/some-url', + legacy: true, + }) + ).toEqual(true); + }); + it('returns false for non-legacy apps', () => { + expect( + isLegacyApp({ + id: 'legacy', + title: 'Legacy App', + mount: () => () => undefined, + legacy: false, + }) + ).toEqual(false); + }); +}); + +describe('relativeToAbsolute', () => { + it('converts a relative path to an absolute url', () => { + const origin = window.location.origin; + expect(relativeToAbsolute('path')).toEqual(`${origin}/path`); + expect(relativeToAbsolute('/path#hash')).toEqual(`${origin}/path#hash`); + expect(relativeToAbsolute('/path?query=foo')).toEqual(`${origin}/path?query=foo`); + }); +}); + +describe('parseAppUrl', () => { + let apps: Map | LegacyApp>; + let basePath: BasePath; + + const getOrigin = () => 'https://kibana.local:8080'; + + const createApp = (props: Partial): App => { + const app: App = { + id: 'some-id', + title: 'some-title', + mount: () => () => undefined, + ...props, + legacy: false, + }; + apps.set(app.id, app); + return app; + }; + + const createLegacyApp = (props: Partial): LegacyApp => { + const app: LegacyApp = { + id: 'some-id', + title: 'some-title', + appUrl: '/my-url', + ...props, + legacy: true, + }; + apps.set(app.id, app); + return app; + }; + + beforeEach(() => { + apps = new Map(); + basePath = new BasePath('/base-path'); + + createApp({ + id: 'foo', + }); + createApp({ + id: 'bar', + appRoute: '/custom-bar', + }); + createLegacyApp({ + id: 'legacy', + appUrl: '/app/legacy', + }); + }); + + describe('with relative paths', () => { + it('parses the app id', () => { + expect(parseAppUrl('/base-path/app/foo', basePath, apps, getOrigin)).toEqual({ + app: 'foo', + path: undefined, + }); + expect(parseAppUrl('/base-path/custom-bar', basePath, apps, getOrigin)).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('parses the path', () => { + expect(parseAppUrl('/base-path/app/foo/some/path', basePath, apps, getOrigin)).toEqual({ + app: 'foo', + path: '/some/path', + }); + expect(parseAppUrl('/base-path/custom-bar/another/path/', basePath, apps, getOrigin)).toEqual( + { + app: 'bar', + path: '/another/path/', + } + ); + }); + it('includes query and hash in the path for default app route', () => { + expect(parseAppUrl('/base-path/app/foo#hash/bang', basePath, apps, getOrigin)).toEqual({ + app: 'foo', + path: '#hash/bang', + }); + expect(parseAppUrl('/base-path/app/foo?hello=dolly', basePath, apps, getOrigin)).toEqual({ + app: 'foo', + path: '?hello=dolly', + }); + expect(parseAppUrl('/base-path/app/foo/path?hello=dolly', basePath, apps, getOrigin)).toEqual( + { + app: 'foo', + path: '/path?hello=dolly', + } + ); + expect(parseAppUrl('/base-path/app/foo/path#hash/bang', basePath, apps, getOrigin)).toEqual({ + app: 'foo', + path: '/path#hash/bang', + }); + expect( + parseAppUrl('/base-path/app/foo/path#hash/bang?hello=dolly', basePath, apps, getOrigin) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('includes query and hash in the path for custom app route', () => { + expect(parseAppUrl('/base-path/custom-bar#hash/bang', basePath, apps, getOrigin)).toEqual({ + app: 'bar', + path: '#hash/bang', + }); + expect(parseAppUrl('/base-path/custom-bar?hello=dolly', basePath, apps, getOrigin)).toEqual({ + app: 'bar', + path: '?hello=dolly', + }); + expect( + parseAppUrl('/base-path/custom-bar/path?hello=dolly', basePath, apps, getOrigin) + ).toEqual({ + app: 'bar', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl('/base-path/custom-bar/path#hash/bang', basePath, apps, getOrigin) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang', + }); + expect( + parseAppUrl('/base-path/custom-bar/path#hash/bang?hello=dolly', basePath, apps, getOrigin) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('works with legacy apps', () => { + expect(parseAppUrl('/base-path/app/legacy', basePath, apps, getOrigin)).toEqual({ + app: 'legacy', + path: undefined, + }); + expect( + parseAppUrl('/base-path/app/legacy/path#hash?query=bar', basePath, apps, getOrigin) + ).toEqual({ + app: 'legacy', + path: '/path#hash?query=bar', + }); + }); + it('returns undefined when the app is not known', () => { + expect(parseAppUrl('/base-path/app/non-registered', basePath, apps, getOrigin)).toEqual( + undefined + ); + expect(parseAppUrl('/base-path/unknown-path', basePath, apps, getOrigin)).toEqual(undefined); + }); + }); + + describe('with absolute urls', () => { + it('parses the app id', () => { + expect( + parseAppUrl('https://kibana.local:8080/base-path/app/foo', basePath, apps, getOrigin) + ).toEqual({ + app: 'foo', + path: undefined, + }); + expect( + parseAppUrl('https://kibana.local:8080/base-path/custom-bar', basePath, apps, getOrigin) + ).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('parses the path', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/some/path', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '/some/path', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/another/path/', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '/another/path/', + }); + }); + it('includes query and hash in the path for default app routes', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo#hash/bang', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path#hash/bang', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path#hash/bang?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('includes query and hash in the path for custom app route', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar#hash/bang', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang?hello=dolly', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('works with legacy apps', () => { + expect( + parseAppUrl('https://kibana.local:8080/base-path/app/legacy', basePath, apps, getOrigin) + ).toEqual({ + app: 'legacy', + path: undefined, + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/legacy/path#hash?query=bar', + basePath, + apps, + getOrigin + ) + ).toEqual({ + app: 'legacy', + path: '/path#hash?query=bar', + }); + }); + it('returns undefined when the app is not known', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/non-registered', + basePath, + apps, + getOrigin + ) + ).toEqual(undefined); + expect( + parseAppUrl('https://kibana.local:8080/base-path/unknown-path', basePath, apps, getOrigin) + ).toEqual(undefined); + }); + it('returns undefined when origin does not match', () => { + expect( + parseAppUrl( + 'https://other-kibana.external:8080/base-path/app/foo', + basePath, + apps, + getOrigin + ) + ).toEqual(undefined); + expect( + parseAppUrl( + 'https://other-kibana.external:8080/base-path/custom-bar', + basePath, + apps, + getOrigin + ) + ).toEqual(undefined); + }); + }); +}); diff --git a/src/core/public/application/utils.ts b/src/core/public/application/utils.ts index 048f195fe12230..8987a9402f2db2 100644 --- a/src/core/public/application/utils.ts +++ b/src/core/public/application/utils.ts @@ -17,6 +17,14 @@ * under the License. */ +import { IBasePath } from '../http'; +import { App, LegacyApp } from './types'; + +export interface AppUrlInfo { + app: string; + path?: string; +} + /** * Utility to remove trailing, leading or duplicate slashes. * By default will only remove duplicates. @@ -52,3 +60,62 @@ export const appendAppPath = (appBasePath: string, path: string = '') => { leading: false, }); }; + +export function isLegacyApp(app: App | LegacyApp): app is LegacyApp { + return app.legacy === true; +} + +/** + * Converts a relative path to an absolute url. + * Implementation is based on a specified behavior of the browser to automatically convert + * a relative url to an absolute one when setting the `href` attribute of a `` html element. + * + * @example + * ```ts + * // current url: `https://kibana:8000/base-path/app/my-app` + * relativeToAbsolute('/base-path/app/another-app') => `https://kibana:8000/base-path/app/another-app` + * ``` + */ +export const relativeToAbsolute = (url: string): string => { + const a = document.createElement('a'); + a.setAttribute('href', url); + return a.href; +}; + +/** + * Parse given url and return the associated app id and path if any app matches. + * Input can either be: + * - a path containing the basePath, ie `/base-path/app/my-app/some-path` + * - an absolute url matching the `origin` of the kibana instance (as seen by the browser), + * i.e `https://kibana:8080/base-path/app/my-app/some-path` + */ +export const parseAppUrl = ( + url: string, + basePath: IBasePath, + apps: Map | LegacyApp>, + getOrigin: () => string = () => window.location.origin +): AppUrlInfo | undefined => { + url = removeBasePath(url, basePath, getOrigin()); + if (!url.startsWith('/')) { + return undefined; + } + + for (const app of apps.values()) { + const appPath = isLegacyApp(app) ? app.appUrl : app.appRoute || `/app/${app.id}`; + + if (url.startsWith(appPath)) { + const path = url.substr(appPath.length); + return { + app: app.id, + path: path.length ? path : undefined, + }; + } + } +}; + +const removeBasePath = (url: string, basePath: IBasePath, origin: string): string => { + if (url.startsWith(origin)) { + url = url.substring(origin.length); + } + return basePath.remove(url); +}; diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index 327be61cc63e39..0bc305ed9e28c9 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -56,7 +56,7 @@ function defaultStartDeps(availableApps?: App[]) { if (availableApps) { deps.application.applications$ = new Rx.BehaviorSubject>( - new Map(availableApps.map(app => [app.id, app])) + new Map(availableApps.map((app) => [app.id, app])) ); } @@ -97,7 +97,9 @@ describe('start', () => { expect(startDeps.notifications.toasts.addWarning.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "Your browser does not meet the security requirements for Kibana.", + Object { + "title": [Function], + }, ], ] `); @@ -131,10 +133,7 @@ describe('start', () => { describe('brand', () => { it('updates/emits the brand as it changes', async () => { const { chrome, service } = await start(); - const promise = chrome - .getBrand$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getBrand$().pipe(toArray()).toPromise(); chrome.setBrand({ logo: 'big logo', @@ -146,28 +145,25 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Object {}, - Object { - "logo": "big logo", - "smallLogo": "not so big logo", - }, - Object { - "logo": "big logo without small logo", - "smallLogo": undefined, - }, - ] - `); + Array [ + Object {}, + Object { + "logo": "big logo", + "smallLogo": "not so big logo", + }, + Object { + "logo": "big logo without small logo", + "smallLogo": undefined, + }, + ] + `); }); }); describe('visibility', () => { it('emits false when no application is mounted', async () => { const { chrome, service } = await start(); - const promise = chrome - .getIsVisible$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getIsVisible$().pipe(toArray()).toPromise(); chrome.setIsVisible(true); chrome.setIsVisible(false); @@ -175,13 +171,13 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - false, - false, - ] - `); + Array [ + false, + false, + false, + false, + ] + `); }); it('emits false until manually overridden when in embed mode', async () => { @@ -190,10 +186,7 @@ describe('start', () => { const { navigateToApp } = startDeps.application; const { chrome, service } = await start({ startDeps }); - const promise = chrome - .getIsVisible$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getIsVisible$().pipe(toArray()).toPromise(); await navigateToApp('alpha'); @@ -203,13 +196,13 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - true, - false, - ] - `); + Array [ + false, + false, + true, + false, + ] + `); }); it('application-specified visibility on mount', async () => { @@ -220,55 +213,46 @@ describe('start', () => { ]); const { applications$, navigateToApp } = startDeps.application; const { chrome, service } = await start({ startDeps }); - const promise = chrome - .getIsVisible$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getIsVisible$().pipe(toArray()).toPromise(); const availableApps = await applications$.pipe(take(1)).toPromise(); - [...availableApps.keys()].forEach(appId => navigateToApp(appId)); + [...availableApps.keys()].forEach((appId) => navigateToApp(appId)); service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - true, - false, - true, - ] - `); + Array [ + false, + true, + false, + true, + ] + `); }); it('changing visibility has no effect on chrome-hiding application', async () => { const startDeps = defaultStartDeps([new FakeApp('alpha', true)]); const { navigateToApp } = startDeps.application; const { chrome, service } = await start({ startDeps }); - const promise = chrome - .getIsVisible$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getIsVisible$().pipe(toArray()).toPromise(); await navigateToApp('alpha'); chrome.setIsVisible(true); service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - false, - false, - false, - ] - `); + Array [ + false, + false, + false, + ] + `); }); }); describe('application classes', () => { it('updates/emits the application classes', async () => { const { chrome, service } = await start(); - const promise = chrome - .getApplicationClasses$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getApplicationClasses$().pipe(toArray()).toPromise(); chrome.addApplicationClass('foo'); chrome.addApplicationClass('foo'); @@ -280,46 +264,43 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Array [], - Array [ - "foo", - ], - Array [ - "foo", - ], - Array [ - "foo", - "bar", - ], - Array [ - "foo", - "bar", - ], - Array [ - "foo", - "bar", - "baz", - ], - Array [ - "foo", - "baz", - ], - Array [ - "baz", - ], - ] - `); + Array [ + Array [], + Array [ + "foo", + ], + Array [ + "foo", + ], + Array [ + "foo", + "bar", + ], + Array [ + "foo", + "bar", + ], + Array [ + "foo", + "bar", + "baz", + ], + Array [ + "foo", + "baz", + ], + Array [ + "baz", + ], + ] + `); }); }); describe('badge', () => { it('updates/emits the current badge', async () => { const { chrome, service } = await start(); - const promise = chrome - .getBadge$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getBadge$().pipe(toArray()).toPromise(); chrome.setBadge({ text: 'foo', tooltip: `foo's tooltip` }); chrome.setBadge({ text: 'bar', tooltip: `bar's tooltip` }); @@ -327,29 +308,26 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - undefined, - Object { - "text": "foo", - "tooltip": "foo's tooltip", - }, - Object { - "text": "bar", - "tooltip": "bar's tooltip", - }, - undefined, - ] - `); + Array [ + undefined, + Object { + "text": "foo", + "tooltip": "foo's tooltip", + }, + Object { + "text": "bar", + "tooltip": "bar's tooltip", + }, + undefined, + ] + `); }); }); describe('breadcrumbs', () => { it('updates/emits the current set of breadcrumbs', async () => { const { chrome, service } = await start(); - const promise = chrome - .getBreadcrumbs$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getBreadcrumbs$().pipe(toArray()).toPromise(); chrome.setBreadcrumbs([{ text: 'foo' }, { text: 'bar' }]); chrome.setBreadcrumbs([{ text: 'foo' }]); @@ -358,39 +336,36 @@ describe('start', () => { service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` - Array [ - Array [], - Array [ - Object { - "text": "foo", - }, - Object { - "text": "bar", - }, - ], - Array [ - Object { - "text": "foo", - }, - ], - Array [ - Object { - "text": "bar", - }, - ], - Array [], - ] - `); + Array [ + Array [], + Array [ + Object { + "text": "foo", + }, + Object { + "text": "bar", + }, + ], + Array [ + Object { + "text": "foo", + }, + ], + Array [ + Object { + "text": "bar", + }, + ], + Array [], + ] + `); }); }); describe('help extension', () => { it('updates/emits the current help extension', async () => { const { chrome, service } = await start(); - const promise = chrome - .getHelpExtension$() - .pipe(toArray()) - .toPromise(); + const promise = chrome.getHelpExtension$().pipe(toArray()).toPromise(); chrome.setHelpExtension({ appName: 'App name', content: () => () => undefined }); chrome.setHelpExtension(undefined); diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index bf1a764e858822..fc7e78f2090222 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -18,11 +18,13 @@ */ import { Breadcrumb as EuiBreadcrumb, IconType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { BehaviorSubject, combineLatest, merge, Observable, of, ReplaySubject } from 'rxjs'; import { flatMap, map, takeUntil } from 'rxjs/operators'; import { parse } from 'url'; +import { EuiLink } from '@elastic/eui'; +import { mountReactNode } from '../utils/mount'; import { InternalApplicationStart } from '../application'; import { DocLinksStart } from '../doc_links'; import { HttpStart } from '../http'; @@ -115,9 +117,9 @@ export class ChromeService { // in the sense that the chrome UI should not be displayed until a non-chromeless app is mounting or mounted of(true), application.currentAppId$.pipe( - flatMap(appId => + flatMap((appId) => application.applications$.pipe( - map(applications => { + map((applications) => { return !!appId && applications.has(appId) && !!applications.get(appId)!.chromeless; }) ) @@ -165,12 +167,44 @@ export class ChromeService { // Can delete const getNavType$ = uiSettings.get$('pageNavigation').pipe(takeUntil(this.stop$)); + const isIE = () => { + const ua = window.navigator.userAgent; + const msie = ua.indexOf('MSIE '); // IE 10 or older + const trident = ua.indexOf('Trident/'); // IE 11 + + return msie > 0 || trident > 0; + }; + if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { - notifications.toasts.addWarning( - i18n.translate('core.chrome.legacyBrowserWarning', { - defaultMessage: 'Your browser does not meet the security requirements for Kibana.', - }) - ); + notifications.toasts.addWarning({ + title: mountReactNode( + + ), + }); + + if (isIE()) { + notifications.toasts.addWarning({ + title: mountReactNode( + + + + ), + }} + /> + ), + }); + } } return { @@ -226,7 +260,7 @@ export class ChromeService { getApplicationClasses$: () => applicationClasses$.pipe( - map(set => [...set]), + map((set) => [...set]), takeUntil(this.stop$) ), diff --git a/src/core/public/chrome/doc_title/doc_title_service.ts b/src/core/public/chrome/doc_title/doc_title_service.ts index 9453abe54de660..c6e9ec7a40b77d 100644 --- a/src/core/public/chrome/doc_title/doc_title_service.ts +++ b/src/core/public/chrome/doc_title/doc_title_service.ts @@ -86,7 +86,7 @@ export class DocTitleService { this.applyTitle(defaultTitle); }, __legacy: { - setBaseTitle: baseTitle => { + setBaseTitle: (baseTitle) => { this.baseTitle = baseTitle; }, }, diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.test.ts b/src/core/public/chrome/nav_controls/nav_controls_service.test.ts index c8f168bbcb2f70..ac556c1d1cc5d6 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.test.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.test.ts @@ -30,12 +30,7 @@ describe('RecentlyAccessed#start()', () => { const navControls = getStart(); const nc = { mount: jest.fn() }; navControls.registerLeft(nc); - expect( - await navControls - .getLeft$() - .pipe(take(1)) - .toPromise() - ).toEqual([nc]); + expect(await navControls.getLeft$().pipe(take(1)).toPromise()).toEqual([nc]); }); it('sorts controls by order property', async () => { @@ -46,12 +41,7 @@ describe('RecentlyAccessed#start()', () => { navControls.registerLeft(nc1); navControls.registerLeft(nc2); navControls.registerLeft(nc3); - expect( - await navControls - .getLeft$() - .pipe(take(1)) - .toPromise() - ).toEqual([nc2, nc1, nc3]); + expect(await navControls.getLeft$().pipe(take(1)).toPromise()).toEqual([nc2, nc1, nc3]); }); }); @@ -60,12 +50,7 @@ describe('RecentlyAccessed#start()', () => { const navControls = getStart(); const nc = { mount: jest.fn() }; navControls.registerRight(nc); - expect( - await navControls - .getRight$() - .pipe(take(1)) - .toPromise() - ).toEqual([nc]); + expect(await navControls.getRight$().pipe(take(1)).toPromise()).toEqual([nc]); }); it('sorts controls by order property', async () => { @@ -76,12 +61,7 @@ describe('RecentlyAccessed#start()', () => { navControls.registerRight(nc1); navControls.registerRight(nc2); navControls.registerRight(nc3); - expect( - await navControls - .getRight$() - .pipe(take(1)) - .toPromise() - ).toEqual([nc2, nc1, nc3]); + expect(await navControls.getRight$().pipe(take(1)).toPromise()).toEqual([nc2, nc1, nc3]); }); }); }); diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.ts b/src/core/public/chrome/nav_controls/nav_controls_service.ts index 7f9c75595a4ce1..167948e01cb362 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -74,12 +74,12 @@ export class NavControlsService { getLeft$: () => navControlsLeft$.pipe( - map(controls => sortBy([...controls.values()], 'order')), + map((controls) => sortBy([...controls.values()], 'order')), takeUntil(this.stop$) ), getRight$: () => navControlsRight$.pipe( - map(controls => sortBy([...controls.values()], 'order')), + map((controls) => sortBy([...controls.values()], 'order')), takeUntil(this.stop$) ), }; diff --git a/src/core/public/chrome/nav_links/nav_links_service.test.ts b/src/core/public/chrome/nav_links/nav_links_service.test.ts index 3d9a4bfdb6a56c..8f610e238b0fd8 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.test.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.test.ts @@ -90,7 +90,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).not.toContain('chromelessApp'); @@ -102,16 +102,16 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).toEqual(['app2', 'legacyApp2', 'app1', 'legacyApp1', 'legacyApp3']); }); it('emits multiple values', async () => { - const navLinkIds$ = start.getNavLinks$().pipe(map(links => links.map(l => l.id))); + const navLinkIds$ = start.getNavLinks$().pipe(map((links) => links.map((l) => l.id))); const emittedLinks: string[][] = []; - navLinkIds$.subscribe(r => emittedLinks.push(r)); + navLinkIds$.subscribe((r) => emittedLinks.push(r)); start.update('legacyApp1', { active: true }); service.stop(); @@ -122,10 +122,7 @@ describe('NavLinksService', () => { }); it('completes when service is stopped', async () => { - const last$ = start - .getNavLinks$() - .pipe(takeLast(1)) - .toPromise(); + const last$ = start.getNavLinks$().pipe(takeLast(1)).toPromise(); service.stop(); await expect(last$).resolves.toBeInstanceOf(Array); }); @@ -143,7 +140,7 @@ describe('NavLinksService', () => { describe('#getAll()', () => { it('returns a sorted array of navlinks', () => { - expect(start.getAll().map(l => l.id)).toEqual([ + expect(start.getAll().map((l) => l.id)).toEqual([ 'app2', 'legacyApp2', 'app1', @@ -171,7 +168,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).toEqual(['app2', 'legacyApp2', 'app1', 'legacyApp1', 'legacyApp3']); @@ -184,7 +181,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).toEqual(['app2', 'legacyApp2', 'app1', 'legacyApp1', 'legacyApp3']); @@ -197,7 +194,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).toEqual(['legacyApp1']); @@ -211,7 +208,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.map(l => l.id)) + map((links) => links.map((l) => l.id)) ) .toPromise() ).toEqual(['legacyApp2']); @@ -236,7 +233,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.filter(l => l.hidden).map(l => l.id)) + map((links) => links.filter((l) => l.hidden).map((l) => l.id)) ) .toPromise(); expect(hiddenLinkIds).toEqual(['legacyApp1']); @@ -253,7 +250,7 @@ describe('NavLinksService', () => { .getNavLinks$() .pipe( take(1), - map(links => links.filter(l => l.hidden).map(l => l.id)) + map((links) => links.filter((l) => l.hidden).map((l) => l.id)) ) .toPromise(); expect(hiddenLinkIds).toEqual(['legacyApp1']); @@ -262,21 +259,15 @@ describe('NavLinksService', () => { describe('#enableForcedAppSwitcherNavigation()', () => { it('flips #getForceAppSwitcherNavigation$()', async () => { - await expect( - start - .getForceAppSwitcherNavigation$() - .pipe(take(1)) - .toPromise() - ).resolves.toBe(false); + await expect(start.getForceAppSwitcherNavigation$().pipe(take(1)).toPromise()).resolves.toBe( + false + ); start.enableForcedAppSwitcherNavigation(); - await expect( - start - .getForceAppSwitcherNavigation$() - .pipe(take(1)) - .toPromise() - ).resolves.toBe(true); + await expect(start.getForceAppSwitcherNavigation$().pipe(take(1)).toPromise()).resolves.toBe( + true + ); }); }); }); diff --git a/src/core/public/chrome/nav_links/nav_links_service.ts b/src/core/public/chrome/nav_links/nav_links_service.ts index fec9322b0d77d7..3095bb86b72e2c 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.ts @@ -108,7 +108,7 @@ export class NavLinksService { public start({ application, http }: StartDeps): ChromeNavLinks { const appLinks$ = application.applications$.pipe( - map(apps => { + map((apps) => { return new Map( [...apps] .filter(([, app]) => !app.chromeless) @@ -129,7 +129,7 @@ export class NavLinksService { return linkUpdaters.reduce((links, updater) => updater(links), appLinks); }) ) - .subscribe(navlinks => { + .subscribe((navlinks) => { navLinks$.next(navlinks); }); @@ -158,7 +158,7 @@ export class NavLinksService { return; } - const updater: LinksUpdater = navLinks => + const updater: LinksUpdater = (navLinks) => new Map([...navLinks.entries()].filter(([linkId]) => linkId === id)); linkUpdaters$.next([...linkUpdaters$.value, updater]); @@ -169,7 +169,7 @@ export class NavLinksService { return; } - const updater: LinksUpdater = navLinks => + const updater: LinksUpdater = (navLinks) => new Map( [...navLinks.entries()].map(([linkId, link]) => { return [linkId, link.id === id ? link.update(values) : link] as [ @@ -200,7 +200,7 @@ export class NavLinksService { function sortNavLinks(navLinks: ReadonlyMap) { return sortBy( - [...navLinks.values()].map(link => link.properties), + [...navLinks.values()].map((link) => link.properties), 'order' ); } diff --git a/src/core/public/chrome/recently_accessed/persisted_log.ts b/src/core/public/chrome/recently_accessed/persisted_log.ts index 421f553f6a315a..ca94e0bcddfaf4 100644 --- a/src/core/public/chrome/recently_accessed/persisted_log.ts +++ b/src/core/public/chrome/recently_accessed/persisted_log.ts @@ -57,7 +57,7 @@ export class PersistedLog { const nextItems = [ val, // remove any duplicate items - ...[...this.items$.value].filter(item => !this.isEqual(item, val)), + ...[...this.items$.value].filter((item) => !this.isEqual(item, val)), ].slice(0, this.maxLength); // truncate // Persist the stack to storage @@ -73,7 +73,7 @@ export class PersistedLog { } public get$() { - return this.items$.pipe(map(items => cloneDeep(items))); + return this.items$.pipe(map((items) => cloneDeep(items))); } private loadItems() { diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 3e3d8c422b9783..866ea5f45d9865 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -275,6 +275,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
@@ -469,6 +471,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="discover" + rel="noreferrer" > @@ -588,6 +592,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="metrics" + rel="noreferrer" > @@ -691,6 +696,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="siem" + rel="noreferrer" >
@@ -1108,6 +1118,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="discover" + rel="noreferrer" > @@ -1227,6 +1239,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="metrics" + rel="noreferrer" > @@ -1330,6 +1343,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` class="euiListGroupItem__button" data-test-subj="collapsibleNavAppLink" href="siem" + rel="noreferrer" >