diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cbdf292964472..5c768dccaf274 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -236,6 +236,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib # Security /src/core/server/csp/ @elastic/kibana-security @elastic/kibana-core /src/plugins/security_oss/ @elastic/kibana-security +/src/plugins/spaces_oss/ @elastic/kibana-security /test/security_functional/ @elastic/kibana-security /x-pack/plugins/spaces/ @elastic/kibana-security /x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security diff --git a/docs/api/dashboard/export-dashboard.asciidoc b/docs/api/dashboard/export-dashboard.asciidoc index d33b9603fae73..6d239d755eb0d 100644 --- a/docs/api/dashboard/export-dashboard.asciidoc +++ b/docs/api/dashboard/export-dashboard.asciidoc @@ -18,6 +18,7 @@ experimental[] Export dashboards and corresponding saved objects. `dashboard`:: (Required, array|string) The IDs of the dashboards that you want to export. + To export multiple dashboards, repeat the query parameter. [[dashboard-api-export-response-body]] ==== Response body diff --git a/docs/apm/images/all-instances.png b/docs/apm/images/all-instances.png new file mode 100644 index 0000000000000..e77c8af2c46f6 Binary files /dev/null and b/docs/apm/images/all-instances.png differ diff --git a/docs/apm/images/error-rate.png b/docs/apm/images/error-rate.png new file mode 100644 index 0000000000000..7e5e32c50f13e Binary files /dev/null and b/docs/apm/images/error-rate.png differ diff --git a/docs/apm/images/latency.png b/docs/apm/images/latency.png new file mode 100644 index 0000000000000..4c970d8c582e6 Binary files /dev/null and b/docs/apm/images/latency.png differ diff --git a/docs/apm/images/metadata-icons.png b/docs/apm/images/metadata-icons.png new file mode 100644 index 0000000000000..dcdac41a7d01a Binary files /dev/null and b/docs/apm/images/metadata-icons.png differ diff --git a/docs/apm/images/spans-dependencies.png b/docs/apm/images/spans-dependencies.png new file mode 100644 index 0000000000000..a827083b5ddcd Binary files /dev/null and b/docs/apm/images/spans-dependencies.png differ diff --git a/docs/apm/images/traffic-transactions.png b/docs/apm/images/traffic-transactions.png new file mode 100644 index 0000000000000..134bc0e6bcb42 Binary files /dev/null and b/docs/apm/images/traffic-transactions.png differ diff --git a/docs/apm/service-overview.asciidoc b/docs/apm/service-overview.asciidoc index 970d4c61ed92e..088791e6098e6 100644 --- a/docs/apm/service-overview.asciidoc +++ b/docs/apm/service-overview.asciidoc @@ -2,4 +2,107 @@ [[service-overview]] === Service overview -Selecting a <> brings you to the *Service overview*. \ No newline at end of file +Selecting a <> brings you to the *Service overview*. +The *Service overview* contains a wide variety of charts and tables that provide +visibility into how a service performs across your infrastructure. + +[discrete] +[[service-latency]] +=== Latency + +Response times for the service. You can filter the *Latency* chart to display the average, +95th, or 99th percentile latency times for the service. + +[role="screenshot"] +image::apm/images/latency.png[Service latency] + +[discrete] +[[service-traffic-transactions]] +=== Traffic and transactions + +The *Throughput* chart visualizes the average number of transactions per minute for the selected service. + +The *Transactions* table displays a list of _transaction groups_ for the +selected service and includes the latency, traffic, error rate, and the impact for each transaction. +Transactions that share the same name are grouped, and only one entry is displayed for each group. + +By default, transaction groups are sorted by _Impact_ to show the most used and slowest endpoints in your +service. If there is a particular endpoint you are interested in, click *View transactions* to view a +list of similar transactions on the <> page. + +[role="screenshot"] +image::apm/images/traffic-transactions.png[Traffic and transactions] + +[discrete] +[[service-error-rates]] +=== Error rate and errors + +The *Error rate* chart displays the average error rates relating to the service, within a specific time range. + +The *Errors* table provides a high-level view of each error message when it first and last occurred, +along with the total number of occurrences. This makes it very easy to quickly see which errors affect +your services and take actions to rectify them. To do so, click *View errors*. + +[role="screenshot"] +image::apm/images/error-rate.png[Error rate and errors] + +[discrete] +[[service-span-duration]] +=== Span types average duration and dependencies + +The *Average duration by span type* chart visualizes each span type's average duration and helps you determine +which spans could be slowing down transactions. The "app" label displayed under the +chart indicates that something was happening within the application. This could signal that the +agent does not have auto-instrumentation for whatever was happening during that time or that the time was spent in the +application code and not in database or external requests. + +The *Dependencies* table displays a list of downstream services or external connections relevant +to the service at the selected time range. The table displays latency, traffic, error rate, and the impact of +each dependency. By default, dependencies are sorted by _Impact_ to show the most used and the slowest dependency. +If there is a particular dependency you are interested in, click *View service map* to view the related +<>. + +[role="screenshot"] +image::apm/images/spans-dependencies.png[Span type duration and dependencies] + +[discrete] +[[service-instances]] +=== All instances + +The *All instances* table displays a list of all the available service instances within the selected time range. +Depending on how the service runs, the instance could be a host or a container. The table displays latency, traffic, +errors, CPU usage, and memory usage for each instance. By default, instances are sorted by _Throughput_. + +[role="screenshot"] +image::apm/images/all-instances.png[All instances] + +[discrete] +[[service-metadata]] +=== Service metadata + +To view metadata relating to the service agent, and if relevant, the container and cloud provider, +click on each icon located at the top of the page beside the service name. + +[role="screenshot"] +image::apm/images/metadata-icons.png[Service metadata] + +*Service information* + +* Service version +* Runtime name and version +* Framework name +* Agent name and version + +*Container information* + +* Operating system +* Containerized - Yes or no. +* Total number of instances +* Orchestration + +*Cloud provider information* + +* Cloud provider +* Availability zones +* Machine types +* Project ID diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index 3f624980e3937..83ca9e5a10a9b 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -24,6 +24,7 @@ Like in the Transaction duration graph, you can zoom in on anomalies to further *Error rate*:: Visualize the total number of transactions with errors divided by the total number of transactions. +The error rate value is based on the `event.outcome` field and is the relative number of failed transactions. Any unexpected increases, decreases, or irregular patterns can be investigated further with the <>. diff --git a/docs/developer/advanced/upgrading-nodejs.asciidoc b/docs/developer/advanced/upgrading-nodejs.asciidoc index a6fa57581772a..c1e727b1eac65 100644 --- a/docs/developer/advanced/upgrading-nodejs.asciidoc +++ b/docs/developer/advanced/upgrading-nodejs.asciidoc @@ -9,7 +9,7 @@ Theses files must be updated when upgrading Node.js: - {kib-repo}blob/{branch}/.ci/Dockerfile[`.ci/Dockerfile`] - The version is specified in the `NODE_VERSION` constant. This is used to pull the relevant image from https://hub.docker.com/_/node[Docker Hub]. - Note that Docker Hub can take 24+ hours to be updated with the new images after a new release of Node.js, so if you're upgrading Node.js in Kibana _just_ after the official Node.js release, you have to check if the new images are present on Docker Hub. + Note that Docker Hub can take 24+ hours to be updated with the new images after a new release of Node.js, so if you're upgrading Node.js in Kibana just after the official Node.js release, you have to check if the new images are present on Docker Hub. If they are not, and the update is urgent, you can skip this file and update it later once Docker Hub has been updated. - {kib-repo}blob/{branch}/.node-version[`.node-version`] - {kib-repo}blob/{branch}/.nvmrc[`.nvmrc`] @@ -29,7 +29,7 @@ Hence, upgrades to either Node.js 14 or Node.js 10 shold be done as separate PRs ==== Node.js patch upgrades -Typically, you want to backport Node.js *patch* upgrades to all supported release branches that run the same _major_ Node.js version: +Typically, you want to backport Node.js *patch* upgrades to all supported release branches that run the same *major* Node.js version: - If upgrading Node.js 14, and the current release is 7.11.1, the main PR should target `master` and be backported to `7.x` and `7.11`. - If upgrading Node.js 10, the main PR should target `6.8` only. diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index c79e46c1d9173..642713e48e833 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -168,10 +168,6 @@ Content is fetched from the remote (https://feeds.elastic.co and https://feeds-s |Create choropleth maps. Display the results of a term-aggregation as e.g. countries, zip-codes, states. -|{kib-repo}blob/{branch}/src/plugins/runtime_fields/README.mdx[runtimeFields] -|The runtime fields plugin provides types and constants for OSS and xpack runtime field related code. - - |{kib-repo}blob/{branch}/src/plugins/saved_objects/README.md[savedObjects] |The savedObjects plugin exposes utilities to manipulate saved objects on the client side. @@ -194,6 +190,10 @@ so they can properly protect the data within their clusters. |Replaces the legacy ui/share module for registering share context menus. +|{kib-repo}blob/{branch}/src/plugins/spaces_oss/README.md[spacesOss] +|Bridge plugin for consumption of the Spaces feature from OSS plugins. + + |{kib-repo}blob/{branch}/src/plugins/telemetry/README.md[telemetry] |Telemetry allows Kibana features to have usage tracked in the wild. The general term "telemetry" refers to multiple things: @@ -487,8 +487,8 @@ Elastic. |Welcome to the Kibana rollup plugin! This plugin provides Kibana support for Elasticsearch's rollup feature. Please refer to the Elasticsearch documentation to understand rollup indices and how to create rollup jobs. -|{kib-repo}blob/{branch}/x-pack/plugins/runtime_field_editor/README.md[runtimeFieldEditor] -|Welcome to the home of the runtime field editor! +|{kib-repo}blob/{branch}/x-pack/plugins/runtime_fields/README.md[runtimeFields] +|Welcome to the home of the runtime field editor and everything related to runtime fields! |{kib-repo}blob/{branch}/x-pack/plugins/saved_objects_tagging/README.md[savedObjectsTagging] diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md index 7bae0bca701bf..c7810b18c55a9 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md @@ -20,6 +20,7 @@ export interface DataPublicPluginStart | [autocomplete](./kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md) | AutocompleteStart | autocomplete service [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md) | | [fieldFormats](./kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md) | FieldFormatsStart | field formats service [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md) | | [indexPatterns](./kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md) | IndexPatternsContract | index patterns service [IndexPatternsContract](./kibana-plugin-plugins-data-public.indexpatternscontract.md) | +| [nowProvider](./kibana-plugin-plugins-data-public.datapublicpluginstart.nowprovider.md) | NowProviderPublicContract | | | [query](./kibana-plugin-plugins-data-public.datapublicpluginstart.query.md) | QueryStart | query service [QueryStart](./kibana-plugin-plugins-data-public.querystart.md) | | [search](./kibana-plugin-plugins-data-public.datapublicpluginstart.search.md) | ISearchStart | search service [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) | | [ui](./kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md) | DataPublicPluginStartUi | prewired UI components [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md) | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.nowprovider.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.nowprovider.md new file mode 100644 index 0000000000000..4a93c25e28815 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.nowprovider.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) > [nowProvider](./kibana-plugin-plugins-data-public.datapublicpluginstart.nowprovider.md) + +## DataPublicPluginStart.nowProvider property + +Signature: + +```typescript +nowProvider: NowProviderPublicContract; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.issynccolorsenabled.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.issynccolorsenabled.md new file mode 100644 index 0000000000000..4a439a1e91316 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.issynccolorsenabled.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-public.executioncontext.issynccolorsenabled.md) + +## ExecutionContext.isSyncColorsEnabled property + +Returns the state (true\|false) of the sync colors across panels switch. + +Signature: + +```typescript +isSyncColorsEnabled?: () => boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md index 1c0d10a382abf..901b46f0888d4 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md @@ -22,6 +22,7 @@ export interface ExecutionContext() => ExecutionContextSearch | Get search context of the expression. | | [getSearchSessionId](./kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md) | () => string | undefined | Search context in which expression should operate. | | [inspectorAdapters](./kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md) | InspectorAdapters | Adapters for inspector plugin. | +| [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-public.executioncontext.issynccolorsenabled.md) | () => boolean | Returns the state (true\|false) of the sync colors across panels switch. | | [types](./kibana-plugin-plugins-expressions-public.executioncontext.types.md) | Record<string, ExpressionType> | A map of available expression types. | | [variables](./kibana-plugin-plugins-expressions-public.executioncontext.variables.md) | Record<string, unknown> | Context variables that can be consumed using var and var_set functions. | diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.issynccolorsenabled.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.issynccolorsenabled.md new file mode 100644 index 0000000000000..24f7bb618deb8 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.issynccolorsenabled.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-server.executioncontext.issynccolorsenabled.md) + +## ExecutionContext.isSyncColorsEnabled property + +Returns the state (true\|false) of the sync colors across panels switch. + +Signature: + +```typescript +isSyncColorsEnabled?: () => boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md index fbf9dc634d563..39018599a2c92 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md @@ -22,6 +22,7 @@ export interface ExecutionContext() => ExecutionContextSearch | Get search context of the expression. | | [getSearchSessionId](./kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md) | () => string | undefined | Search context in which expression should operate. | | [inspectorAdapters](./kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md) | InspectorAdapters | Adapters for inspector plugin. | +| [isSyncColorsEnabled](./kibana-plugin-plugins-expressions-server.executioncontext.issynccolorsenabled.md) | () => boolean | Returns the state (true\|false) of the sync colors across panels switch. | | [types](./kibana-plugin-plugins-expressions-server.executioncontext.types.md) | Record<string, ExpressionType> | A map of available expression types. | | [variables](./kibana-plugin-plugins-expressions-server.executioncontext.variables.md) | Record<string, unknown> | Context variables that can be consumed using var and var_set functions. | diff --git a/docs/discover/images/Discover-Start.png b/docs/discover/images/Discover-Start.png old mode 100755 new mode 100644 index 437684fdbcd79..28c30865844b4 Binary files a/docs/discover/images/Discover-Start.png and b/docs/discover/images/Discover-Start.png differ diff --git a/docs/discover/images/document-table-expanded.png b/docs/discover/images/document-table-expanded.png old mode 100755 new mode 100644 index 052ffbc9cbcc4..f92fdd8747fa4 Binary files a/docs/discover/images/document-table-expanded.png and b/docs/discover/images/document-table-expanded.png differ diff --git a/docs/discover/images/document-table.png b/docs/discover/images/document-table.png index 7aca8b14ae1f7..5b0383b522cea 100644 Binary files a/docs/discover/images/document-table.png and b/docs/discover/images/document-table.png differ diff --git a/docs/discover/images/visualize-from-discover.png b/docs/discover/images/visualize-from-discover.png index 17ef6002b19bd..9543112eb88ca 100644 Binary files a/docs/discover/images/visualize-from-discover.png and b/docs/discover/images/visualize-from-discover.png differ diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc index feb16190cb34b..8c0012fb6c6bf 100644 --- a/docs/discover/kuery.asciidoc +++ b/docs/discover/kuery.asciidoc @@ -111,13 +111,35 @@ tags:(success and info and security) [discrete] === Range queries -KQL supports `>`, `>=`, `<`, and `<=` on numeric and date types. For example: +KQL supports `>`, `>=`, `<`, and `<=` on numeric and date types. [source,yaml] ------------------- -account_number >= 100 and items_sold <= 200 and @timestamp >= now-5m +account_number >= 100 and items_sold <= 200 ------------------- +[discrete] +=== Date range queries + +Typically, Kibana's <> is sufficient for setting a time range, +but in some cases you might need to search on dates. Include the date range in quotes. + +[source,yaml] +------------------- +@timestamp < "2021-01-02T21:55:59" +------------------- + +[source,yaml] +------------------- +@timestamp < "2021-01" +------------------- + +[source,yaml] +------------------- +@timestamp < "2021" +------------------- + + [discrete] === Exist queries diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index febdf707dce9a..6dd76f782d668 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -231,6 +231,16 @@ This value must be a whole number greater than zero. *Default: `"1000"`* suggestions. This value must be a whole number greater than zero. *Default: `"100000"`* +|=== + +[NOTE] +============ +To reload the logging settings, send a SIGHUP signal to {kib}. +============ + +[cols="2*<"] +|=== + |[[logging-dest]] `logging.dest:` | Enables you to specify a file where {kib} stores log output. *Default: `stdout`* diff --git a/docs/user/reporting/response-codes.asciidoc b/docs/user/reporting/response-codes.asciidoc index 5ec9bf5300124..50a27766f37fb 100644 --- a/docs/user/reporting/response-codes.asciidoc +++ b/docs/user/reporting/response-codes.asciidoc @@ -9,7 +9,7 @@ the POST URL. This is true even if the job somehow fails later, since report generation happens asynchronously from queuing. - **`400` (Bad Request)**: When sending requests to the POST URL, if you don't use - `POST` as the HTTP method, or if your request is missing the `kbn-version` header, + `POST` as the HTTP method, or if your request is missing the `kbn-xsrf` header, Kibana will return a code `400` status response for the request. - **`503` (Service Unavailable)**: When using the `path` to request the download, you diff --git a/docs/user/reporting/script-example.asciidoc b/docs/user/reporting/script-example.asciidoc index 94301fc6fb448..56721d20ea3c7 100644 --- a/docs/user/reporting/script-example.asciidoc +++ b/docs/user/reporting/script-example.asciidoc @@ -3,7 +3,7 @@ The response from this request will be JSON, and will contain a `path` property URL to use to download the generated report. Use the `GET` method in the HTTP request to download the report. -The request method must be `POST` and it must include a `kbn-version` header for Kibana +The request method must be `POST` and it must include a `kbn-xsrf` header for Kibana to allow the request. The following example queues CSV report generation using the `POST` URL with cURL: @@ -13,7 +13,7 @@ The following example queues CSV report generation using the `POST` URL with cUR curl \ -XPOST \ <1> -u elastic \ <2> --H 'kbn-version: {version}' \ <3> +-H 'kbn-xsrf: true' \ <3> 'http://0.0.0.0:5601/api/reporting/generate/csv?jobParams=...' <4> --------------------------------------------------------- // CONSOLE @@ -21,8 +21,8 @@ curl \ <1> `POST` method is required. <2> Provide user credentials for a user with permission to access Kibana and {report-features}. -<3> The `kbn-version` header is required for all `POST` requests to Kibana. -**The value must match the dotted-numeral version of the Kibana instance.** +<3> The `kbn-xsrf` header is required for all `POST` requests to Kibana. For more information, see <>. <4> The POST URL. You can copy and paste the URL for any report from the Kibana UI. Here is an example response for a successfully queued report: diff --git a/package.json b/package.json index 8af20d6459373..b9c2e9c7f0bfd 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "@kbn/utils": "link:packages/kbn-utils", "@loaders.gl/core": "^2.3.1", "@loaders.gl/json": "^2.3.1", - "@slack/webhook": "^5.0.0", + "@slack/webhook": "^5.0.4", "@storybook/addons": "^6.0.16", "@turf/along": "6.0.1", "@turf/area": "6.0.1", @@ -170,7 +170,7 @@ "apollo-server-errors": "^2.0.2", "apollo-server-hapi": "^1.3.6", "archiver": "^3.1.1", - "axios": "^0.19.2", + "axios": "^0.21.1", "bluebird": "3.5.5", "brace": "0.11.1", "chalk": "^4.1.0", @@ -195,7 +195,7 @@ "dedent": "^0.7.0", "deep-freeze-strict": "^1.1.1", "del": "^5.1.0", - "elastic-apm-node": "^3.7.0", + "elastic-apm-node": "^3.10.0", "elasticsearch": "^16.7.0", "execa": "^4.0.2", "exit-hook": "^2.2.0", @@ -391,7 +391,7 @@ "@microsoft/api-documenter": "7.7.2", "@microsoft/api-extractor": "7.7.0", "@octokit/rest": "^16.35.0", - "@percy/agent": "^0.26.0", + "@percy/agent": "^0.28.6", "@scant/router": "^0.1.0", "@storybook/addon-a11y": "^6.0.26", "@storybook/addon-actions": "^6.0.26", @@ -440,6 +440,7 @@ "@types/enzyme": "^3.10.5", "@types/eslint": "^6.1.3", "@types/extract-zip": "^1.6.2", + "@types/faker": "^5.1.5", "@types/fancy-log": "^1.3.1", "@types/fetch-mock": "^7.3.1", "@types/file-saver": "^2.0.0", @@ -489,6 +490,7 @@ "@types/md5": "^2.2.0", "@types/memoize-one": "^4.1.0", "@types/mime": "^2.0.1", + "@types/mime-types": "^2.1.0", "@types/minimatch": "^2.0.29", "@types/mocha": "^7.0.2", "@types/mock-fs": "^4.10.0", @@ -592,13 +594,13 @@ "babel-plugin-require-context-hook": "^1.0.0", "babel-plugin-styled-components": "^1.10.7", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "backport": "5.6.0", + "backport": "^5.6.1", "base64-js": "^1.3.1", "base64url": "^3.0.1", "broadcast-channel": "^3.0.3", "chai": "3.5.0", "chance": "1.0.18", - "chromedriver": "^87.0.0", + "chromedriver": "^87.0.3", "clean-webpack-plugin": "^3.0.0", "cmd-shim": "^2.1.0", "compare-versions": "3.5.1", @@ -647,7 +649,7 @@ "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-perf": "^3.2.3", "expose-loader": "^0.7.5", - "faker": "1.1.0", + "faker": "^5.1.0", "fancy-log": "^1.3.2", "fast-glob": "2.2.7", "fetch-mock": "^7.3.9", @@ -829,13 +831,13 @@ "url-loader": "^2.2.0", "use-resize-observer": "^6.0.0", "val-loader": "^1.1.1", - "vega": "^5.17.3", + "vega": "^5.18.0", "vega-lite": "^4.17.0", "vega-schema-url-parser": "^2.1.0", "vega-tooltip": "^0.25.0", "venn.js": "0.2.20", "vinyl-fs": "^3.0.3", - "wait-on": "^5.0.1", + "wait-on": "^5.2.1", "watchpack": "^1.6.0", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.0", diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 67287089489e1..44cc4fdabb25e 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -102,7 +102,7 @@ pageLoadAssetSize: visualizations: 295025 visualize: 57431 watcher: 43598 - runtimeFields: 10000 + runtimeFields: 41752 stackAlerts: 29684 presentationUtil: 28545 - runtimeFieldEditor: 46986 + spacesOss: 18817 diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 922159ab555c8..955a375228d55 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(511); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(510); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(248); @@ -106,7 +106,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(251); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return _utils_package_json__WEBPACK_IMPORTED_MODULE_4__["transformDependencies"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(510); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(509); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -150,7 +150,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(128); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(504); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(503); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(246); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2981,16 +2981,20 @@ var ReplaySubject = /*@__PURE__*/ (function (_super) { return _this; } ReplaySubject.prototype.nextInfiniteTimeWindow = function (value) { - var _events = this._events; - _events.push(value); - if (_events.length > this._bufferSize) { - _events.shift(); + if (!this.isStopped) { + var _events = this._events; + _events.push(value); + if (_events.length > this._bufferSize) { + _events.shift(); + } } _super.prototype.next.call(this, value); }; ReplaySubject.prototype.nextTimeWindow = function (value) { - this._events.push(new ReplayEvent(this._getNow(), value)); - this._trimBufferThenGetEvents(); + if (!this.isStopped) { + this._events.push(new ReplayEvent(this._getNow(), value)); + this._trimBufferThenGetEvents(); + } _super.prototype.next.call(this, value); }; ReplaySubject.prototype._subscribe = function (subscriber) { @@ -8897,9 +8901,9 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(129); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(372); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(403); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(404); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(371); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(402); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(403); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8942,10 +8946,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(246); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(247); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(248); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(364); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(369); -/* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(366); -/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(370); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(363); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(368); +/* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(365); +/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(369); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -33849,7 +33853,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(320); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(356); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(355); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(246); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } @@ -33947,13 +33951,13 @@ const childProcess = __webpack_require__(321); const crossSpawn = __webpack_require__(322); const stripFinalNewline = __webpack_require__(335); const npmRunPath = __webpack_require__(336); -const onetime = __webpack_require__(338); -const makeError = __webpack_require__(340); -const normalizeStdio = __webpack_require__(345); -const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(346); -const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(347); -const {mergePromise, getSpawnedPromise} = __webpack_require__(354); -const {joinCommand, parseCommand} = __webpack_require__(355); +const onetime = __webpack_require__(337); +const makeError = __webpack_require__(339); +const normalizeStdio = __webpack_require__(344); +const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(345); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(346); +const {mergePromise, getSpawnedPromise} = __webpack_require__(353); +const {joinCommand, parseCommand} = __webpack_require__(354); const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; @@ -34358,13 +34362,14 @@ module.exports = parse; const path = __webpack_require__(4); const which = __webpack_require__(325); -const pathKey = __webpack_require__(329)(); +const getPathKey = __webpack_require__(329); function resolveCommandAttempt(parsed, withoutPathExt) { + const env = parsed.options.env || process.env; const cwd = process.cwd(); const hasCustomCwd = parsed.options.cwd != null; // Worker threads do not have process.chdir() - const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined; + const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled; // If a custom `cwd` was specified, we need to change the process cwd // because `which` will do stat calls but does not support a custom cwd @@ -34380,7 +34385,7 @@ function resolveCommandAttempt(parsed, withoutPathExt) { try { resolved = which.sync(parsed.command, { - path: (parsed.options.env || process.env)[pathKey], + path: env[getPathKey({ env })], pathExt: withoutPathExt ? path.delimiter : undefined, }); } catch (e) { @@ -34932,7 +34937,7 @@ module.exports = input => { "use strict"; const path = __webpack_require__(4); -const pathKey = __webpack_require__(337); +const pathKey = __webpack_require__(329); const npmRunPath = options => { options = { @@ -34985,30 +34990,7 @@ module.exports.env = options => { "use strict"; - -const pathKey = (options = {}) => { - const environment = options.env || process.env; - const platform = options.platform || process.platform; - - if (platform !== 'win32') { - return 'PATH'; - } - - return Object.keys(environment).find(key => key.toUpperCase() === 'PATH') || 'Path'; -}; - -module.exports = pathKey; -// TODO: Remove this for the next major release -module.exports.default = pathKey; - - -/***/ }), -/* 338 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const mimicFn = __webpack_require__(339); +const mimicFn = __webpack_require__(338); const calledFunctions = new WeakMap(); @@ -35060,7 +35042,7 @@ module.exports.callCount = fn => { /***/ }), -/* 339 */ +/* 338 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35080,12 +35062,12 @@ module.exports.default = mimicFn; /***/ }), -/* 340 */ +/* 339 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {signalsByName} = __webpack_require__(341); +const {signalsByName} = __webpack_require__(340); const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { if (timedOut) { @@ -35173,14 +35155,14 @@ module.exports = makeError; /***/ }), -/* 341 */ +/* 340 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(121); -var _signals=__webpack_require__(342); -var _realtime=__webpack_require__(344); +var _signals=__webpack_require__(341); +var _realtime=__webpack_require__(343); @@ -35250,14 +35232,14 @@ const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumb //# sourceMappingURL=main.js.map /***/ }), -/* 342 */ +/* 341 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(121); -var _core=__webpack_require__(343); -var _realtime=__webpack_require__(344); +var _core=__webpack_require__(342); +var _realtime=__webpack_require__(343); @@ -35291,7 +35273,7 @@ return{name,number,description,supported,action,forced,standard}; //# sourceMappingURL=signals.js.map /***/ }), -/* 343 */ +/* 342 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35570,7 +35552,7 @@ standard:"other"}];exports.SIGNALS=SIGNALS; //# sourceMappingURL=core.js.map /***/ }), -/* 344 */ +/* 343 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35595,7 +35577,7 @@ const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; //# sourceMappingURL=realtime.js.map /***/ }), -/* 345 */ +/* 344 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35654,7 +35636,7 @@ module.exports.node = opts => { /***/ }), -/* 346 */ +/* 345 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35773,14 +35755,14 @@ module.exports = { /***/ }), -/* 347 */ +/* 346 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isStream = __webpack_require__(348); -const getStream = __webpack_require__(349); -const mergeStream = __webpack_require__(353); +const isStream = __webpack_require__(347); +const getStream = __webpack_require__(348); +const mergeStream = __webpack_require__(352); // `input` option const handleInput = (spawned, input) => { @@ -35877,7 +35859,7 @@ module.exports = { /***/ }), -/* 348 */ +/* 347 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35913,13 +35895,13 @@ module.exports = isStream; /***/ }), -/* 349 */ +/* 348 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pump = __webpack_require__(350); -const bufferStream = __webpack_require__(352); +const pump = __webpack_require__(349); +const bufferStream = __webpack_require__(351); class MaxBufferError extends Error { constructor() { @@ -35978,11 +35960,11 @@ module.exports.MaxBufferError = MaxBufferError; /***/ }), -/* 350 */ +/* 349 */ /***/ (function(module, exports, __webpack_require__) { var once = __webpack_require__(162) -var eos = __webpack_require__(351) +var eos = __webpack_require__(350) var fs = __webpack_require__(134) // we only need fs to get the ReadStream and WriteStream prototypes var noop = function () {} @@ -36066,7 +36048,7 @@ module.exports = pump /***/ }), -/* 351 */ +/* 350 */ /***/ (function(module, exports, __webpack_require__) { var once = __webpack_require__(162); @@ -36166,7 +36148,7 @@ module.exports = eos; /***/ }), -/* 352 */ +/* 351 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36225,7 +36207,7 @@ module.exports = options => { /***/ }), -/* 353 */ +/* 352 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36273,7 +36255,7 @@ module.exports = function (/*streams...*/) { /***/ }), -/* 354 */ +/* 353 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36326,7 +36308,7 @@ module.exports = { /***/ }), -/* 355 */ +/* 354 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36371,7 +36353,7 @@ module.exports = { /***/ }), -/* 356 */ +/* 355 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -36379,12 +36361,12 @@ module.exports = { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(357); -module.exports.cli = __webpack_require__(361); +module.exports = __webpack_require__(356); +module.exports.cli = __webpack_require__(360); /***/ }), -/* 357 */ +/* 356 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36399,9 +36381,9 @@ var stream = __webpack_require__(138); var util = __webpack_require__(112); var fs = __webpack_require__(134); -var through = __webpack_require__(358); -var duplexer = __webpack_require__(359); -var StringDecoder = __webpack_require__(360).StringDecoder; +var through = __webpack_require__(357); +var duplexer = __webpack_require__(358); +var StringDecoder = __webpack_require__(359).StringDecoder; module.exports = Logger; @@ -36590,7 +36572,7 @@ function lineMerger(host) { /***/ }), -/* 358 */ +/* 357 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(138) @@ -36704,7 +36686,7 @@ function through (write, end, opts) { /***/ }), -/* 359 */ +/* 358 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(138) @@ -36797,13 +36779,13 @@ function duplex(writer, reader) { /***/ }), -/* 360 */ +/* 359 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 361 */ +/* 360 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36814,11 +36796,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(362); +var minimist = __webpack_require__(361); var path = __webpack_require__(4); -var Logger = __webpack_require__(357); -var pkg = __webpack_require__(363); +var Logger = __webpack_require__(356); +var pkg = __webpack_require__(362); module.exports = cli; @@ -36872,7 +36854,7 @@ function usage($0, p) { /***/ }), -/* 362 */ +/* 361 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -37123,13 +37105,13 @@ function isNumber (x) { /***/ }), -/* 363 */ +/* 362 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 364 */ +/* 363 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -37137,13 +37119,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(134); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(365); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(364); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(112); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(320); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(366); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(365); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -37342,20 +37324,20 @@ async function getAllChecksums(kbn, log, yarnLock) { } /***/ }), -/* 365 */ +/* 364 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 366 */ +/* 365 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resolveDepsForProject", function() { return resolveDepsForProject; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(367); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(366); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(131); /* @@ -37468,7 +37450,7 @@ function resolveDepsForProject({ } /***/ }), -/* 367 */ +/* 366 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -39027,7 +39009,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(365); +module.exports = __webpack_require__(364); /***/ }), /* 10 */, @@ -41351,7 +41333,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(368); +module.exports = __webpack_require__(367); /***/ }), /* 64 */, @@ -47746,13 +47728,13 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 368 */ +/* 367 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 369 */ +/* 368 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -47849,13 +47831,13 @@ class BootstrapCacheFile { } /***/ }), -/* 370 */ +/* 369 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateDependencies", function() { return validateDependencies; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(367); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(366); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_1__); @@ -47866,7 +47848,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(246); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(251); -/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(371); +/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(370); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -48058,7 +48040,7 @@ function getDevOnlyProductionDepsTree(kbn, projectName) { } /***/ }), -/* 371 */ +/* 370 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -48211,7 +48193,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 372 */ +/* 371 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -48219,7 +48201,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(143); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(373); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(372); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); @@ -48319,20 +48301,20 @@ const CleanCommand = { }; /***/ }), -/* 373 */ +/* 372 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readline = __webpack_require__(374); -const chalk = __webpack_require__(375); -const cliCursor = __webpack_require__(382); -const cliSpinners = __webpack_require__(384); -const logSymbols = __webpack_require__(386); -const stripAnsi = __webpack_require__(395); -const wcwidth = __webpack_require__(397); -const isInteractive = __webpack_require__(401); -const MuteStream = __webpack_require__(402); +const readline = __webpack_require__(373); +const chalk = __webpack_require__(374); +const cliCursor = __webpack_require__(381); +const cliSpinners = __webpack_require__(383); +const logSymbols = __webpack_require__(385); +const stripAnsi = __webpack_require__(394); +const wcwidth = __webpack_require__(396); +const isInteractive = __webpack_require__(400); +const MuteStream = __webpack_require__(401); const TEXT = Symbol('text'); const PREFIX_TEXT = Symbol('prefixText'); @@ -48685,23 +48667,23 @@ module.exports.promise = (action, options) => { /***/ }), -/* 374 */ +/* 373 */ /***/ (function(module, exports) { module.exports = require("readline"); /***/ }), -/* 375 */ +/* 374 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(376); +const ansiStyles = __webpack_require__(375); const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(120); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(380); +} = __webpack_require__(379); // `supportsColor.level` → `ansiStyles.color[name]` mapping const levelMapping = [ @@ -48902,7 +48884,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(381); + template = __webpack_require__(380); } return template(chalk, parts.join('')); @@ -48931,7 +48913,7 @@ module.exports = chalk; /***/ }), -/* 376 */ +/* 375 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48977,7 +48959,7 @@ const setLazyProperty = (object, property, get) => { let colorConvert; const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { if (colorConvert === undefined) { - colorConvert = __webpack_require__(377); + colorConvert = __webpack_require__(376); } const offset = isBackground ? 10 : 0; @@ -49102,11 +49084,11 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 377 */ +/* 376 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(378); -const route = __webpack_require__(379); +const conversions = __webpack_require__(377); +const route = __webpack_require__(378); const convert = {}; @@ -49189,7 +49171,7 @@ module.exports = convert; /***/ }), -/* 378 */ +/* 377 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ @@ -50034,10 +50016,10 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 379 */ +/* 378 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(378); +const conversions = __webpack_require__(377); /* This function routes a model to all other models. @@ -50137,7 +50119,7 @@ module.exports = function (fromModel) { /***/ }), -/* 380 */ +/* 379 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50183,7 +50165,7 @@ module.exports = { /***/ }), -/* 381 */ +/* 380 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50324,12 +50306,12 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 382 */ +/* 381 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(383); +const restoreCursor = __webpack_require__(382); let isHidden = false; @@ -50366,12 +50348,12 @@ exports.toggle = (force, writableStream) => { /***/ }), -/* 383 */ +/* 382 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(338); +const onetime = __webpack_require__(337); const signalExit = __webpack_require__(309); module.exports = onetime(() => { @@ -50382,13 +50364,13 @@ module.exports = onetime(() => { /***/ }), -/* 384 */ +/* 383 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const spinners = Object.assign({}, __webpack_require__(385)); +const spinners = Object.assign({}, __webpack_require__(384)); const spinnersList = Object.keys(spinners); @@ -50406,18 +50388,18 @@ module.exports.default = spinners; /***/ }), -/* 385 */ +/* 384 */ /***/ (function(module) { -module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]}}"); +module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]},\"aesthetic\":{\"interval\":80,\"frames\":[\"▰▱▱▱▱▱▱\",\"▰▰▱▱▱▱▱\",\"▰▰▰▱▱▱▱\",\"▰▰▰▰▱▱▱\",\"▰▰▰▰▰▱▱\",\"▰▰▰▰▰▰▱\",\"▰▰▰▰▰▰▰\",\"▰▱▱▱▱▱▱\"]}}"); /***/ }), -/* 386 */ +/* 385 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(387); +const chalk = __webpack_require__(386); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -50439,16 +50421,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 387 */ +/* 386 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(265); -const ansiStyles = __webpack_require__(388); -const stdoutColor = __webpack_require__(393).stdout; +const ansiStyles = __webpack_require__(387); +const stdoutColor = __webpack_require__(392).stdout; -const template = __webpack_require__(394); +const template = __webpack_require__(393); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -50674,12 +50656,12 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 388 */ +/* 387 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(389); +const colorConvert = __webpack_require__(388); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -50847,11 +50829,11 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 389 */ +/* 388 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(390); -var route = __webpack_require__(392); +var conversions = __webpack_require__(389); +var route = __webpack_require__(391); var convert = {}; @@ -50931,11 +50913,11 @@ module.exports = convert; /***/ }), -/* 390 */ +/* 389 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ -var cssKeywords = __webpack_require__(391); +var cssKeywords = __webpack_require__(390); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -51805,7 +51787,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 391 */ +/* 390 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51964,10 +51946,10 @@ module.exports = { /***/ }), -/* 392 */ +/* 391 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(390); +var conversions = __webpack_require__(389); /* this function routes a model to all other models. @@ -52067,7 +52049,7 @@ module.exports = function (fromModel) { /***/ }), -/* 393 */ +/* 392 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52205,7 +52187,7 @@ module.exports = { /***/ }), -/* 394 */ +/* 393 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52340,18 +52322,18 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 395 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(396); +const ansiRegex = __webpack_require__(395); module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; /***/ }), -/* 396 */ +/* 395 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52368,14 +52350,14 @@ module.exports = ({onlyFirst = false} = {}) => { /***/ }), -/* 397 */ +/* 396 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var defaults = __webpack_require__(398) -var combining = __webpack_require__(400) +var defaults = __webpack_require__(397) +var combining = __webpack_require__(399) var DEFAULTS = { nul: 0, @@ -52474,10 +52456,10 @@ function bisearch(ucs) { /***/ }), -/* 398 */ +/* 397 */ /***/ (function(module, exports, __webpack_require__) { -var clone = __webpack_require__(399); +var clone = __webpack_require__(398); module.exports = function(options, defaults) { options = options || {}; @@ -52492,7 +52474,7 @@ module.exports = function(options, defaults) { }; /***/ }), -/* 399 */ +/* 398 */ /***/ (function(module, exports, __webpack_require__) { var clone = (function() { @@ -52664,7 +52646,7 @@ if ( true && module.exports) { /***/ }), -/* 400 */ +/* 399 */ /***/ (function(module, exports) { module.exports = [ @@ -52720,7 +52702,7 @@ module.exports = [ /***/ }), -/* 401 */ +/* 400 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52736,7 +52718,7 @@ module.exports = ({stream = process.stdout} = {}) => { /***/ }), -/* 402 */ +/* 401 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(138) @@ -52887,7 +52869,7 @@ MuteStream.prototype.close = proxy('close') /***/ }), -/* 403 */ +/* 402 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52948,7 +52930,7 @@ const RunCommand = { }; /***/ }), -/* 404 */ +/* 403 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52958,7 +52940,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(248); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(405); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(404); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -53044,14 +53026,14 @@ const WatchCommand = { }; /***/ }), -/* 405 */ +/* 404 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(406); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(405); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -53118,141 +53100,141 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 406 */ +/* 405 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(407); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(406); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(408); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(407); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(409); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(408); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(410); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(409); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(411); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(410); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(412); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(411); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(413); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(412); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(414); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(413); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(415); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(414); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(416); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(415); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(417); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(416); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); /* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(80); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(418); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(417); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(419); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(418); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(420); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(419); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(421); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(420); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(422); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(421); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(423); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(422); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(424); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(423); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(426); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(425); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(427); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(426); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(428); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(427); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(429); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(430); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(431); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(430); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(434); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(435); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(436); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(437); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(438); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(437); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); /* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(105); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(439); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(440); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(441); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(442); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); /* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(31); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(443); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(444); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(445); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); /* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(66); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(447); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(448); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(449); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(452); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(451); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); /* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(81); @@ -53263,175 +53245,175 @@ __webpack_require__.r(__webpack_exports__); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["flatMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(453); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(454); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(453); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(455); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(456); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); /* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(41); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(457); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(458); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(459); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(460); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(461); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(462); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(463); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(464); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(465); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(450); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(466); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(467); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(468); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(469); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); /* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(30); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(470); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(471); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(451); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(472); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(473); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(474); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(475); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(474); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(476); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(475); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(477); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(476); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(478); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(477); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(479); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(478); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(480); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(479); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(481); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(480); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(483); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(482); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(484); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(483); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(485); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(433); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(432); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(446); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(486); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(485); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(487); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(486); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(488); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(487); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(489); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(488); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(490); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(489); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(432); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(491); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(490); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(492); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(491); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(493); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(492); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(494); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(493); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(495); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(494); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(496); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(495); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(497); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(496); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(498); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(497); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(499); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(498); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(500); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(501); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(500); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(502); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(501); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(503); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(502); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -53542,7 +53524,7 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 407 */ +/* 406 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53621,14 +53603,14 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 408 */ +/* 407 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(407); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(406); /* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(108); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -53644,7 +53626,7 @@ function auditTime(duration, scheduler) { /***/ }), -/* 409 */ +/* 408 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53691,7 +53673,7 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 410 */ +/* 409 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53792,7 +53774,7 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 411 */ +/* 410 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53953,7 +53935,7 @@ function dispatchBufferClose(arg) { /***/ }), -/* 412 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54072,7 +54054,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 413 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54165,7 +54147,7 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 414 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54225,7 +54207,7 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 415 */ +/* 414 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54241,7 +54223,7 @@ function combineAll(project) { /***/ }), -/* 416 */ +/* 415 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54273,7 +54255,7 @@ function combineLatest() { /***/ }), -/* 417 */ +/* 416 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54293,7 +54275,7 @@ function concat() { /***/ }), -/* 418 */ +/* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54309,13 +54291,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 419 */ +/* 418 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(418); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(417); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -54325,7 +54307,7 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 420 */ +/* 419 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54390,7 +54372,7 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 421 */ +/* 420 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54475,7 +54457,7 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 422 */ +/* 421 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54551,7 +54533,7 @@ function dispatchNext(subscriber) { /***/ }), -/* 423 */ +/* 422 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54601,7 +54583,7 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 424 */ +/* 423 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54609,7 +54591,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(425); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); /* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(42); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -54708,7 +54690,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 425 */ +/* 424 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54722,7 +54704,7 @@ function isDate(value) { /***/ }), -/* 426 */ +/* 425 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54868,7 +54850,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 427 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54906,7 +54888,7 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 428 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54982,7 +54964,7 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 429 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55053,13 +55035,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 430 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(429); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(428); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -55069,7 +55051,7 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 431 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55077,9 +55059,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); /* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(432); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(423); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(433); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(431); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(422); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(432); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -55101,7 +55083,7 @@ function elementAt(index, defaultValue) { /***/ }), -/* 432 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55167,7 +55149,7 @@ function defaultErrorFactory() { /***/ }), -/* 433 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55229,7 +55211,7 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 434 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55251,7 +55233,7 @@ function endWith() { /***/ }), -/* 435 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55313,7 +55295,7 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 436 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55367,7 +55349,7 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 437 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55461,7 +55443,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 438 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55573,7 +55555,7 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 439 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55611,7 +55593,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 440 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55683,13 +55665,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 441 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(440); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(439); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -55699,7 +55681,7 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 442 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55707,9 +55689,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(433); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(423); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(432); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(432); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(422); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(431); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -55726,7 +55708,7 @@ function first(predicate, defaultValue) { /***/ }), -/* 443 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55763,7 +55745,7 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 444 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55807,7 +55789,7 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 445 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55815,9 +55797,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(446); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(432); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(423); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(445); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(431); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(422); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -55834,7 +55816,7 @@ function last(predicate, defaultValue) { /***/ }), -/* 446 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55911,7 +55893,7 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 447 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55950,7 +55932,7 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 448 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56000,13 +55982,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 449 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(450); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -56019,15 +56001,15 @@ function max(comparer) { /***/ }), -/* 450 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(451); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(446); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(423); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(450); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(445); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(422); /* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(24); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -56048,7 +56030,7 @@ function reduce(accumulator, seed) { /***/ }), -/* 451 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56130,7 +56112,7 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 452 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56150,7 +56132,7 @@ function merge() { /***/ }), -/* 453 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56175,7 +56157,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 454 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56284,13 +56266,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 455 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(450); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -56303,7 +56285,7 @@ function min(comparer) { /***/ }), -/* 456 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56352,7 +56334,7 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 457 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56442,7 +56424,7 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 458 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56490,7 +56472,7 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 459 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56513,7 +56495,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 460 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56553,14 +56535,14 @@ function plucker(props, length) { /***/ }), -/* 461 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(456); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -56573,14 +56555,14 @@ function publish(selector) { /***/ }), -/* 462 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); /* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(32); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(456); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -56591,14 +56573,14 @@ function publishBehavior(value) { /***/ }), -/* 463 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); /* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(456); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -56609,14 +56591,14 @@ function publishLast() { /***/ }), -/* 464 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); /* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(33); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(456); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(455); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -56632,7 +56614,7 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 465 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56659,7 +56641,7 @@ function race() { /***/ }), -/* 466 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56724,7 +56706,7 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 467 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56818,7 +56800,7 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 468 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56871,7 +56853,7 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 469 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56957,7 +56939,7 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 470 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57012,7 +56994,7 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 471 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57072,7 +57054,7 @@ function dispatchNotification(state) { /***/ }), -/* 472 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57195,13 +57177,13 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 473 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(456); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455); /* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(27); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -57218,7 +57200,7 @@ function share() { /***/ }), -/* 474 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57287,7 +57269,7 @@ function shareReplayOperator(_a) { /***/ }), -/* 475 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57367,7 +57349,7 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 476 */ +/* 475 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57409,7 +57391,7 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 477 */ +/* 476 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57471,7 +57453,7 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 478 */ +/* 477 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57528,7 +57510,7 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 479 */ +/* 478 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57584,7 +57566,7 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 480 */ +/* 479 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57613,13 +57595,13 @@ function startWith() { /***/ }), -/* 481 */ +/* 480 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(482); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(481); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -57644,7 +57626,7 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 482 */ +/* 481 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57708,13 +57690,13 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 483 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(484); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -57726,7 +57708,7 @@ function switchAll() { /***/ }), -/* 484 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57814,13 +57796,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 485 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(484); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(483); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -57830,7 +57812,7 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 486 */ +/* 485 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57878,7 +57860,7 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 487 */ +/* 486 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57946,7 +57928,7 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 488 */ +/* 487 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58034,7 +58016,7 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 489 */ +/* 488 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58136,7 +58118,7 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 490 */ +/* 489 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58145,7 +58127,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(55); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(489); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(488); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -58234,7 +58216,7 @@ function dispatchNext(arg) { /***/ }), -/* 491 */ +/* 490 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58242,7 +58224,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(451); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(450); /* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(66); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -58278,7 +58260,7 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 492 */ +/* 491 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58286,7 +58268,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); /* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(64); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(493); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(492); /* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(49); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -58303,7 +58285,7 @@ function timeout(due, scheduler) { /***/ }), -/* 493 */ +/* 492 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58311,7 +58293,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(425); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); /* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */ @@ -58382,7 +58364,7 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 494 */ +/* 493 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58412,13 +58394,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 495 */ +/* 494 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(450); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(449); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -58435,7 +58417,7 @@ function toArray() { /***/ }), -/* 496 */ +/* 495 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58513,7 +58495,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 497 */ +/* 496 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58603,7 +58585,7 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 498 */ +/* 497 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58773,7 +58755,7 @@ function dispatchWindowClose(state) { /***/ }), -/* 499 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58916,7 +58898,7 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 500 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59013,7 +58995,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 501 */ +/* 500 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59108,7 +59090,7 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 502 */ +/* 501 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59130,7 +59112,7 @@ function zip() { /***/ }), -/* 503 */ +/* 502 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59146,7 +59128,7 @@ function zipAll(project) { /***/ }), -/* 504 */ +/* 503 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59155,8 +59137,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(249); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(248); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(371); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(505); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(370); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(504); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -59238,7 +59220,7 @@ function toArray(value) { } /***/ }), -/* 505 */ +/* 504 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59246,13 +59228,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(506); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(505); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(366); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(365); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(248); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(510); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(509); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -59414,15 +59396,15 @@ class Kibana { } /***/ }), -/* 506 */ +/* 505 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(150); -const arrayUnion = __webpack_require__(507); -const arrayDiffer = __webpack_require__(508); -const arrify = __webpack_require__(509); +const arrayUnion = __webpack_require__(506); +const arrayDiffer = __webpack_require__(507); +const arrify = __webpack_require__(508); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -59446,7 +59428,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 507 */ +/* 506 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59458,7 +59440,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 508 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59473,7 +59455,7 @@ module.exports = arrayDiffer; /***/ }), -/* 509 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59503,7 +59485,7 @@ module.exports = arrify; /***/ }), -/* 510 */ +/* 509 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59573,12 +59555,12 @@ function getProjectPaths({ } /***/ }), -/* 511 */ +/* 510 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(512); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(511); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); /* @@ -59602,19 +59584,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 512 */ +/* 511 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(513); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(512); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(510); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(509); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(246); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(251); @@ -59751,7 +59733,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 513 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59759,14 +59741,14 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(156); const path = __webpack_require__(4); const os = __webpack_require__(121); -const pMap = __webpack_require__(514); -const arrify = __webpack_require__(509); -const globby = __webpack_require__(515); -const hasGlob = __webpack_require__(715); -const cpFile = __webpack_require__(717); -const junk = __webpack_require__(727); -const pFilter = __webpack_require__(728); -const CpyError = __webpack_require__(730); +const pMap = __webpack_require__(513); +const arrify = __webpack_require__(508); +const globby = __webpack_require__(514); +const hasGlob = __webpack_require__(714); +const cpFile = __webpack_require__(716); +const junk = __webpack_require__(726); +const pFilter = __webpack_require__(727); +const CpyError = __webpack_require__(729); const defaultOptions = { ignoreJunk: true @@ -59917,7 +59899,7 @@ module.exports = (source, destination, { /***/ }), -/* 514 */ +/* 513 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60005,17 +59987,17 @@ module.exports = async ( /***/ }), -/* 515 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const arrayUnion = __webpack_require__(516); +const arrayUnion = __webpack_require__(515); const glob = __webpack_require__(147); -const fastGlob = __webpack_require__(518); -const dirGlob = __webpack_require__(708); -const gitignore = __webpack_require__(711); +const fastGlob = __webpack_require__(517); +const dirGlob = __webpack_require__(707); +const gitignore = __webpack_require__(710); const DEFAULT_FILTER = () => false; @@ -60160,12 +60142,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 516 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(517); +var arrayUniq = __webpack_require__(516); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -60173,7 +60155,7 @@ module.exports = function () { /***/ }), -/* 517 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60242,10 +60224,10 @@ if ('Set' in global) { /***/ }), -/* 518 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(519); +const pkg = __webpack_require__(518); module.exports = pkg.async; module.exports.default = pkg.async; @@ -60258,19 +60240,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 519 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(520); -var taskManager = __webpack_require__(521); -var reader_async_1 = __webpack_require__(679); -var reader_stream_1 = __webpack_require__(703); -var reader_sync_1 = __webpack_require__(704); -var arrayUtils = __webpack_require__(706); -var streamUtils = __webpack_require__(707); +var optionsManager = __webpack_require__(519); +var taskManager = __webpack_require__(520); +var reader_async_1 = __webpack_require__(678); +var reader_stream_1 = __webpack_require__(702); +var reader_sync_1 = __webpack_require__(703); +var arrayUtils = __webpack_require__(705); +var streamUtils = __webpack_require__(706); /** * Synchronous API. */ @@ -60336,7 +60318,7 @@ function isString(source) { /***/ }), -/* 520 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60374,13 +60356,13 @@ exports.prepare = prepare; /***/ }), -/* 521 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(522); +var patternUtils = __webpack_require__(521); /** * Generate tasks based on parent directory of each pattern. */ @@ -60471,16 +60453,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 522 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var globParent = __webpack_require__(523); +var globParent = __webpack_require__(522); var isGlob = __webpack_require__(172); -var micromatch = __webpack_require__(526); +var micromatch = __webpack_require__(525); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -60626,15 +60608,15 @@ exports.matchAny = matchAny; /***/ }), -/* 523 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var isglob = __webpack_require__(524); -var pathDirname = __webpack_require__(525); +var isglob = __webpack_require__(523); +var pathDirname = __webpack_require__(524); var isWin32 = __webpack_require__(121).platform() === 'win32'; module.exports = function globParent(str) { @@ -60657,7 +60639,7 @@ module.exports = function globParent(str) { /***/ }), -/* 524 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -60688,7 +60670,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 525 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60838,7 +60820,7 @@ module.exports.win32 = win32; /***/ }), -/* 526 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60849,18 +60831,18 @@ module.exports.win32 = win32; */ var util = __webpack_require__(112); -var braces = __webpack_require__(527); -var toRegex = __webpack_require__(528); -var extend = __webpack_require__(645); +var braces = __webpack_require__(526); +var toRegex = __webpack_require__(527); +var extend = __webpack_require__(644); /** * Local dependencies */ -var compilers = __webpack_require__(647); -var parsers = __webpack_require__(674); -var cache = __webpack_require__(675); -var utils = __webpack_require__(676); +var compilers = __webpack_require__(646); +var parsers = __webpack_require__(673); +var cache = __webpack_require__(674); +var utils = __webpack_require__(675); var MAX_LENGTH = 1024 * 64; /** @@ -61722,7 +61704,7 @@ module.exports = micromatch; /***/ }), -/* 527 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61732,18 +61714,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(528); -var unique = __webpack_require__(550); -var extend = __webpack_require__(551); +var toRegex = __webpack_require__(527); +var unique = __webpack_require__(549); +var extend = __webpack_require__(550); /** * Local dependencies */ -var compilers = __webpack_require__(553); -var parsers = __webpack_require__(568); -var Braces = __webpack_require__(572); -var utils = __webpack_require__(554); +var compilers = __webpack_require__(552); +var parsers = __webpack_require__(567); +var Braces = __webpack_require__(571); +var utils = __webpack_require__(553); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -62047,16 +62029,16 @@ module.exports = braces; /***/ }), -/* 528 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(529); -var define = __webpack_require__(535); -var extend = __webpack_require__(543); -var not = __webpack_require__(547); +var safe = __webpack_require__(528); +var define = __webpack_require__(534); +var extend = __webpack_require__(542); +var not = __webpack_require__(546); var MAX_LENGTH = 1024 * 64; /** @@ -62209,10 +62191,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 529 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(530); +var parse = __webpack_require__(529); var types = parse.types; module.exports = function (re, opts) { @@ -62258,13 +62240,13 @@ function isRegExp (x) { /***/ }), -/* 530 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(531); -var types = __webpack_require__(532); -var sets = __webpack_require__(533); -var positions = __webpack_require__(534); +var util = __webpack_require__(530); +var types = __webpack_require__(531); +var sets = __webpack_require__(532); +var positions = __webpack_require__(533); module.exports = function(regexpStr) { @@ -62546,11 +62528,11 @@ module.exports.types = types; /***/ }), -/* 531 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(532); -var sets = __webpack_require__(533); +var types = __webpack_require__(531); +var sets = __webpack_require__(532); // All of these are private and only used by randexp. @@ -62663,7 +62645,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 532 */ +/* 531 */ /***/ (function(module, exports) { module.exports = { @@ -62679,10 +62661,10 @@ module.exports = { /***/ }), -/* 533 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(532); +var types = __webpack_require__(531); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -62767,10 +62749,10 @@ exports.anyChar = function() { /***/ }), -/* 534 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(532); +var types = __webpack_require__(531); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -62790,7 +62772,7 @@ exports.end = function() { /***/ }), -/* 535 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62803,8 +62785,8 @@ exports.end = function() { -var isobject = __webpack_require__(536); -var isDescriptor = __webpack_require__(537); +var isobject = __webpack_require__(535); +var isDescriptor = __webpack_require__(536); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -62835,7 +62817,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 536 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62854,7 +62836,7 @@ module.exports = function isObject(val) { /***/ }), -/* 537 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62867,9 +62849,9 @@ module.exports = function isObject(val) { -var typeOf = __webpack_require__(538); -var isAccessor = __webpack_require__(539); -var isData = __webpack_require__(541); +var typeOf = __webpack_require__(537); +var isAccessor = __webpack_require__(538); +var isData = __webpack_require__(540); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -62883,7 +62865,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 538 */ +/* 537 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -63018,7 +63000,7 @@ function isBuffer(val) { /***/ }), -/* 539 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63031,7 +63013,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(540); +var typeOf = __webpack_require__(539); // accessor descriptor properties var accessor = { @@ -63094,7 +63076,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 540 */ +/* 539 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -63229,7 +63211,7 @@ function isBuffer(val) { /***/ }), -/* 541 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63242,7 +63224,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(542); +var typeOf = __webpack_require__(541); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -63285,7 +63267,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 542 */ +/* 541 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -63420,14 +63402,14 @@ function isBuffer(val) { /***/ }), -/* 543 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(544); -var assignSymbols = __webpack_require__(546); +var isExtendable = __webpack_require__(543); +var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -63487,7 +63469,7 @@ function isEnum(obj, key) { /***/ }), -/* 544 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63500,7 +63482,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -63508,7 +63490,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 545 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63521,7 +63503,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(536); +var isObject = __webpack_require__(535); function isObjectObject(o) { return isObject(o) === true @@ -63552,7 +63534,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 546 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63599,14 +63581,14 @@ module.exports = function(receiver, objects) { /***/ }), -/* 547 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(548); -var safe = __webpack_require__(529); +var extend = __webpack_require__(547); +var safe = __webpack_require__(528); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -63678,14 +63660,14 @@ module.exports = toRegex; /***/ }), -/* 548 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(549); -var assignSymbols = __webpack_require__(546); +var isExtendable = __webpack_require__(548); +var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -63745,7 +63727,7 @@ function isEnum(obj, key) { /***/ }), -/* 549 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63758,7 +63740,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -63766,7 +63748,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 550 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63816,13 +63798,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 551 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(552); +var isObject = __webpack_require__(551); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -63856,7 +63838,7 @@ function hasOwn(obj, key) { /***/ }), -/* 552 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63876,13 +63858,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 553 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(554); +var utils = __webpack_require__(553); module.exports = function(braces, options) { braces.compiler @@ -64165,25 +64147,25 @@ function hasQueue(node) { /***/ }), -/* 554 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(555); +var splitString = __webpack_require__(554); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(551); -utils.flatten = __webpack_require__(558); -utils.isObject = __webpack_require__(536); -utils.fillRange = __webpack_require__(559); -utils.repeat = __webpack_require__(567); -utils.unique = __webpack_require__(550); +utils.extend = __webpack_require__(550); +utils.flatten = __webpack_require__(557); +utils.isObject = __webpack_require__(535); +utils.fillRange = __webpack_require__(558); +utils.repeat = __webpack_require__(566); +utils.unique = __webpack_require__(549); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -64515,7 +64497,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 555 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64528,7 +64510,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(556); +var extend = __webpack_require__(555); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -64693,14 +64675,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 556 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(557); -var assignSymbols = __webpack_require__(546); +var isExtendable = __webpack_require__(556); +var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -64760,7 +64742,7 @@ function isEnum(obj, key) { /***/ }), -/* 557 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64773,7 +64755,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -64781,7 +64763,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 558 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64810,7 +64792,7 @@ function flat(arr, res) { /***/ }), -/* 559 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64824,10 +64806,10 @@ function flat(arr, res) { var util = __webpack_require__(112); -var isNumber = __webpack_require__(560); -var extend = __webpack_require__(563); -var repeat = __webpack_require__(565); -var toRegex = __webpack_require__(566); +var isNumber = __webpack_require__(559); +var extend = __webpack_require__(562); +var repeat = __webpack_require__(564); +var toRegex = __webpack_require__(565); /** * Return a range of numbers or letters. @@ -65025,7 +65007,7 @@ module.exports = fillRange; /***/ }), -/* 560 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65038,7 +65020,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(561); +var typeOf = __webpack_require__(560); module.exports = function isNumber(num) { var type = typeOf(num); @@ -65054,10 +65036,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 561 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(562); +var isBuffer = __webpack_require__(561); var toString = Object.prototype.toString; /** @@ -65176,7 +65158,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, exports) { /*! @@ -65203,13 +65185,13 @@ function isSlowBuffer (obj) { /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(564); +var isObject = __webpack_require__(563); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -65243,7 +65225,7 @@ function hasOwn(obj, key) { /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65263,7 +65245,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65340,7 +65322,7 @@ function repeat(str, num) { /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65353,8 +65335,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(565); -var isNumber = __webpack_require__(560); +var repeat = __webpack_require__(564); +var isNumber = __webpack_require__(559); var cache = {}; function toRegexRange(min, max, options) { @@ -65641,7 +65623,7 @@ module.exports = toRegexRange; /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65666,14 +65648,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(569); -var utils = __webpack_require__(554); +var Node = __webpack_require__(568); +var utils = __webpack_require__(553); /** * Braces parsers @@ -66033,15 +66015,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(536); -var define = __webpack_require__(570); -var utils = __webpack_require__(571); +var isObject = __webpack_require__(535); +var define = __webpack_require__(569); +var utils = __webpack_require__(570); var ownNames; /** @@ -66532,7 +66514,7 @@ exports = module.exports = Node; /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66545,7 +66527,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(537); +var isDescriptor = __webpack_require__(536); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -66570,13 +66552,13 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(561); +var typeOf = __webpack_require__(560); var utils = module.exports; /** @@ -67596,17 +67578,17 @@ function assert(val, message) { /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(551); -var Snapdragon = __webpack_require__(573); -var compilers = __webpack_require__(553); -var parsers = __webpack_require__(568); -var utils = __webpack_require__(554); +var extend = __webpack_require__(550); +var Snapdragon = __webpack_require__(572); +var compilers = __webpack_require__(552); +var parsers = __webpack_require__(567); +var utils = __webpack_require__(553); /** * Customize Snapdragon parser and renderer @@ -67707,17 +67689,17 @@ module.exports = Braces; /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(574); -var define = __webpack_require__(603); -var Compiler = __webpack_require__(613); -var Parser = __webpack_require__(642); -var utils = __webpack_require__(622); +var Base = __webpack_require__(573); +var define = __webpack_require__(602); +var Compiler = __webpack_require__(612); +var Parser = __webpack_require__(641); +var utils = __webpack_require__(621); var regexCache = {}; var cache = {}; @@ -67888,20 +67870,20 @@ module.exports.Parser = Parser; /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var define = __webpack_require__(575); -var CacheBase = __webpack_require__(576); -var Emitter = __webpack_require__(577); -var isObject = __webpack_require__(536); -var merge = __webpack_require__(597); -var pascal = __webpack_require__(600); -var cu = __webpack_require__(601); +var define = __webpack_require__(574); +var CacheBase = __webpack_require__(575); +var Emitter = __webpack_require__(576); +var isObject = __webpack_require__(535); +var merge = __webpack_require__(596); +var pascal = __webpack_require__(599); +var cu = __webpack_require__(600); /** * Optionally define a custom `cache` namespace to use. @@ -68330,7 +68312,7 @@ module.exports.namespace = namespace; /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68343,7 +68325,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(537); +var isDescriptor = __webpack_require__(536); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -68368,21 +68350,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(536); -var Emitter = __webpack_require__(577); -var visit = __webpack_require__(578); -var toPath = __webpack_require__(581); -var union = __webpack_require__(582); -var del = __webpack_require__(588); -var get = __webpack_require__(585); -var has = __webpack_require__(593); -var set = __webpack_require__(596); +var isObject = __webpack_require__(535); +var Emitter = __webpack_require__(576); +var visit = __webpack_require__(577); +var toPath = __webpack_require__(580); +var union = __webpack_require__(581); +var del = __webpack_require__(587); +var get = __webpack_require__(584); +var has = __webpack_require__(592); +var set = __webpack_require__(595); /** * Create a `Cache` constructor that when instantiated will @@ -68636,7 +68618,7 @@ module.exports.namespace = namespace; /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { @@ -68805,7 +68787,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68818,8 +68800,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(579); -var mapVisit = __webpack_require__(580); +var visit = __webpack_require__(578); +var mapVisit = __webpack_require__(579); module.exports = function(collection, method, val) { var result; @@ -68842,7 +68824,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68855,7 +68837,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(536); +var isObject = __webpack_require__(535); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -68882,14 +68864,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var visit = __webpack_require__(579); +var visit = __webpack_require__(578); /** * Map `visit` over an array of objects. @@ -68926,7 +68908,7 @@ function isObject(val) { /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68939,7 +68921,7 @@ function isObject(val) { -var typeOf = __webpack_require__(561); +var typeOf = __webpack_require__(560); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -68966,16 +68948,16 @@ function filter(arr) { /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(583); -var union = __webpack_require__(584); -var get = __webpack_require__(585); -var set = __webpack_require__(586); +var isObject = __webpack_require__(582); +var union = __webpack_require__(583); +var get = __webpack_require__(584); +var set = __webpack_require__(585); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -69003,7 +68985,7 @@ function arrayify(val) { /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69023,7 +69005,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69059,7 +69041,7 @@ module.exports = function union(init) { /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, exports) { /*! @@ -69115,7 +69097,7 @@ function toString(val) { /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69128,10 +69110,10 @@ function toString(val) { -var split = __webpack_require__(555); -var extend = __webpack_require__(587); -var isPlainObject = __webpack_require__(545); -var isObject = __webpack_require__(583); +var split = __webpack_require__(554); +var extend = __webpack_require__(586); +var isPlainObject = __webpack_require__(544); +var isObject = __webpack_require__(582); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -69177,13 +69159,13 @@ function isValidKey(key) { /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(583); +var isObject = __webpack_require__(582); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -69217,7 +69199,7 @@ function hasOwn(obj, key) { /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69230,8 +69212,8 @@ function hasOwn(obj, key) { -var isObject = __webpack_require__(536); -var has = __webpack_require__(589); +var isObject = __webpack_require__(535); +var has = __webpack_require__(588); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -69256,7 +69238,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69269,9 +69251,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(590); -var hasValues = __webpack_require__(592); -var get = __webpack_require__(585); +var isObject = __webpack_require__(589); +var hasValues = __webpack_require__(591); +var get = __webpack_require__(584); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -69282,7 +69264,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69295,7 +69277,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(591); +var isArray = __webpack_require__(590); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -69303,7 +69285,7 @@ module.exports = function isObject(val) { /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -69314,7 +69296,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69357,7 +69339,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69370,9 +69352,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(536); -var hasValues = __webpack_require__(594); -var get = __webpack_require__(585); +var isObject = __webpack_require__(535); +var hasValues = __webpack_require__(593); +var get = __webpack_require__(584); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -69380,7 +69362,7 @@ module.exports = function(val, prop) { /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69393,8 +69375,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(595); -var isNumber = __webpack_require__(560); +var typeOf = __webpack_require__(594); +var isNumber = __webpack_require__(559); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -69447,10 +69429,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(562); +var isBuffer = __webpack_require__(561); var toString = Object.prototype.toString; /** @@ -69572,7 +69554,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69585,10 +69567,10 @@ module.exports = function kindOf(val) { -var split = __webpack_require__(555); -var extend = __webpack_require__(587); -var isPlainObject = __webpack_require__(545); -var isObject = __webpack_require__(583); +var split = __webpack_require__(554); +var extend = __webpack_require__(586); +var isPlainObject = __webpack_require__(544); +var isObject = __webpack_require__(582); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -69634,14 +69616,14 @@ function isValidKey(key) { /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(598); -var forIn = __webpack_require__(599); +var isExtendable = __webpack_require__(597); +var forIn = __webpack_require__(598); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -69705,7 +69687,7 @@ module.exports = mixinDeep; /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69718,7 +69700,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -69726,7 +69708,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69749,7 +69731,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports) { /*! @@ -69776,14 +69758,14 @@ module.exports = pascalcase; /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var utils = __webpack_require__(602); +var utils = __webpack_require__(601); /** * Expose class utils @@ -70148,7 +70130,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70162,10 +70144,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(584); -utils.define = __webpack_require__(603); -utils.isObj = __webpack_require__(536); -utils.staticExtend = __webpack_require__(610); +utils.union = __webpack_require__(583); +utils.define = __webpack_require__(602); +utils.isObj = __webpack_require__(535); +utils.staticExtend = __webpack_require__(609); /** @@ -70176,7 +70158,7 @@ module.exports = utils; /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70189,7 +70171,7 @@ module.exports = utils; -var isDescriptor = __webpack_require__(604); +var isDescriptor = __webpack_require__(603); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -70214,7 +70196,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70227,9 +70209,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(605); -var isAccessor = __webpack_require__(606); -var isData = __webpack_require__(608); +var typeOf = __webpack_require__(604); +var isAccessor = __webpack_require__(605); +var isData = __webpack_require__(607); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -70243,7 +70225,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -70396,7 +70378,7 @@ function isBuffer(val) { /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70409,7 +70391,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(607); +var typeOf = __webpack_require__(606); // accessor descriptor properties var accessor = { @@ -70472,10 +70454,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(562); +var isBuffer = __webpack_require__(561); var toString = Object.prototype.toString; /** @@ -70594,7 +70576,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70607,7 +70589,7 @@ module.exports = function kindOf(val) { -var typeOf = __webpack_require__(609); +var typeOf = __webpack_require__(608); // data descriptor properties var data = { @@ -70656,10 +70638,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(562); +var isBuffer = __webpack_require__(561); var toString = Object.prototype.toString; /** @@ -70778,7 +70760,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70791,8 +70773,8 @@ module.exports = function kindOf(val) { -var copy = __webpack_require__(611); -var define = __webpack_require__(603); +var copy = __webpack_require__(610); +var define = __webpack_require__(602); var util = __webpack_require__(112); /** @@ -70875,15 +70857,15 @@ module.exports = extend; /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(561); -var copyDescriptor = __webpack_require__(612); -var define = __webpack_require__(603); +var typeOf = __webpack_require__(560); +var copyDescriptor = __webpack_require__(611); +var define = __webpack_require__(602); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -71056,7 +71038,7 @@ module.exports.has = has; /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71144,16 +71126,16 @@ function isObject(val) { /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(614); -var define = __webpack_require__(603); -var debug = __webpack_require__(616)('snapdragon:compiler'); -var utils = __webpack_require__(622); +var use = __webpack_require__(613); +var define = __webpack_require__(602); +var debug = __webpack_require__(615)('snapdragon:compiler'); +var utils = __webpack_require__(621); /** * Create a new `Compiler` with the given `options`. @@ -71307,7 +71289,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(641); + var sourcemaps = __webpack_require__(640); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -71328,7 +71310,7 @@ module.exports = Compiler; /***/ }), -/* 614 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71341,7 +71323,7 @@ module.exports = Compiler; -var utils = __webpack_require__(615); +var utils = __webpack_require__(614); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -71456,7 +71438,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 615 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71470,8 +71452,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(603); -utils.isObject = __webpack_require__(536); +utils.define = __webpack_require__(602); +utils.isObject = __webpack_require__(535); utils.isString = function(val) { @@ -71486,7 +71468,7 @@ module.exports = utils; /***/ }), -/* 616 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71495,14 +71477,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(617); + module.exports = __webpack_require__(616); } else { - module.exports = __webpack_require__(620); + module.exports = __webpack_require__(619); } /***/ }), -/* 617 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71511,7 +71493,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(618); +exports = module.exports = __webpack_require__(617); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -71693,7 +71675,7 @@ function localstorage() { /***/ }), -/* 618 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { @@ -71709,7 +71691,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(619); +exports.humanize = __webpack_require__(618); /** * The currently active debug mode names, and names to skip. @@ -71901,7 +71883,7 @@ function coerce(val) { /***/ }), -/* 619 */ +/* 618 */ /***/ (function(module, exports) { /** @@ -72059,7 +72041,7 @@ function plural(ms, n, name) { /***/ }), -/* 620 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -72075,7 +72057,7 @@ var util = __webpack_require__(112); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(618); +exports = module.exports = __webpack_require__(617); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -72254,7 +72236,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(621); + var net = __webpack_require__(620); stream = new net.Socket({ fd: fd, readable: false, @@ -72313,13 +72295,13 @@ exports.enable(load()); /***/ }), -/* 621 */ +/* 620 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 622 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72329,9 +72311,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(587); -exports.SourceMap = __webpack_require__(623); -exports.sourceMapResolve = __webpack_require__(634); +exports.extend = __webpack_require__(586); +exports.SourceMap = __webpack_require__(622); +exports.sourceMapResolve = __webpack_require__(633); /** * Convert backslash in the given string to forward slashes @@ -72374,7 +72356,7 @@ exports.last = function(arr, n) { /***/ }), -/* 623 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -72382,13 +72364,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(624).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(630).SourceMapConsumer; -exports.SourceNode = __webpack_require__(633).SourceNode; +exports.SourceMapGenerator = __webpack_require__(623).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(629).SourceMapConsumer; +exports.SourceNode = __webpack_require__(632).SourceNode; /***/ }), -/* 624 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72398,10 +72380,10 @@ exports.SourceNode = __webpack_require__(633).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(625); -var util = __webpack_require__(627); -var ArraySet = __webpack_require__(628).ArraySet; -var MappingList = __webpack_require__(629).MappingList; +var base64VLQ = __webpack_require__(624); +var util = __webpack_require__(626); +var ArraySet = __webpack_require__(627).ArraySet; +var MappingList = __webpack_require__(628).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -72810,7 +72792,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 625 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72850,7 +72832,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(626); +var base64 = __webpack_require__(625); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -72956,7 +72938,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 626 */ +/* 625 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73029,7 +73011,7 @@ exports.decode = function (charCode) { /***/ }), -/* 627 */ +/* 626 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73452,7 +73434,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 628 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73462,7 +73444,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(627); +var util = __webpack_require__(626); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -73579,7 +73561,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 629 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73589,7 +73571,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(627); +var util = __webpack_require__(626); /** * Determine whether mappingB is after mappingA with respect to generated @@ -73664,7 +73646,7 @@ exports.MappingList = MappingList; /***/ }), -/* 630 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73674,11 +73656,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(627); -var binarySearch = __webpack_require__(631); -var ArraySet = __webpack_require__(628).ArraySet; -var base64VLQ = __webpack_require__(625); -var quickSort = __webpack_require__(632).quickSort; +var util = __webpack_require__(626); +var binarySearch = __webpack_require__(630); +var ArraySet = __webpack_require__(627).ArraySet; +var base64VLQ = __webpack_require__(624); +var quickSort = __webpack_require__(631).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -74752,7 +74734,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 631 */ +/* 630 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74869,7 +74851,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 632 */ +/* 631 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74989,7 +74971,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 633 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74999,8 +74981,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(624).SourceMapGenerator; -var util = __webpack_require__(627); +var SourceMapGenerator = __webpack_require__(623).SourceMapGenerator; +var util = __webpack_require__(626); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -75408,17 +75390,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 634 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(635) -var resolveUrl = __webpack_require__(636) -var decodeUriComponent = __webpack_require__(637) -var urix = __webpack_require__(639) -var atob = __webpack_require__(640) +var sourceMappingURL = __webpack_require__(634) +var resolveUrl = __webpack_require__(635) +var decodeUriComponent = __webpack_require__(636) +var urix = __webpack_require__(638) +var atob = __webpack_require__(639) @@ -75716,7 +75698,7 @@ module.exports = { /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -75779,7 +75761,7 @@ void (function(root, factory) { /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75797,13 +75779,13 @@ module.exports = resolveUrl /***/ }), -/* 637 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(638) +var decodeUriComponent = __webpack_require__(637) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -75814,7 +75796,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 638 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75915,7 +75897,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 639 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75938,7 +75920,7 @@ module.exports = urix /***/ }), -/* 640 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75952,7 +75934,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 641 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75960,8 +75942,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(134); var path = __webpack_require__(4); -var define = __webpack_require__(603); -var utils = __webpack_require__(622); +var define = __webpack_require__(602); +var utils = __webpack_require__(621); /** * Expose `mixin()`. @@ -76104,19 +76086,19 @@ exports.comment = function(node) { /***/ }), -/* 642 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(614); +var use = __webpack_require__(613); var util = __webpack_require__(112); -var Cache = __webpack_require__(643); -var define = __webpack_require__(603); -var debug = __webpack_require__(616)('snapdragon:parser'); -var Position = __webpack_require__(644); -var utils = __webpack_require__(622); +var Cache = __webpack_require__(642); +var define = __webpack_require__(602); +var debug = __webpack_require__(615)('snapdragon:parser'); +var Position = __webpack_require__(643); +var utils = __webpack_require__(621); /** * Create a new `Parser` with the given `input` and `options`. @@ -76644,7 +76626,7 @@ module.exports = Parser; /***/ }), -/* 643 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76751,13 +76733,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 644 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(603); +var define = __webpack_require__(602); /** * Store position for a node @@ -76772,14 +76754,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 645 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(646); -var assignSymbols = __webpack_require__(546); +var isExtendable = __webpack_require__(645); +var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -76839,7 +76821,7 @@ function isEnum(obj, key) { /***/ }), -/* 646 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76852,7 +76834,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -76860,14 +76842,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 647 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(648); -var extglob = __webpack_require__(663); +var nanomatch = __webpack_require__(647); +var extglob = __webpack_require__(662); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -76944,7 +76926,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 648 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76955,17 +76937,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(112); -var toRegex = __webpack_require__(528); -var extend = __webpack_require__(649); +var toRegex = __webpack_require__(527); +var extend = __webpack_require__(648); /** * Local dependencies */ -var compilers = __webpack_require__(651); -var parsers = __webpack_require__(652); -var cache = __webpack_require__(655); -var utils = __webpack_require__(657); +var compilers = __webpack_require__(650); +var parsers = __webpack_require__(651); +var cache = __webpack_require__(654); +var utils = __webpack_require__(656); var MAX_LENGTH = 1024 * 64; /** @@ -77789,14 +77771,14 @@ module.exports = nanomatch; /***/ }), -/* 649 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(650); -var assignSymbols = __webpack_require__(546); +var isExtendable = __webpack_require__(649); +var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -77856,7 +77838,7 @@ function isEnum(obj, key) { /***/ }), -/* 650 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77869,7 +77851,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(545); +var isPlainObject = __webpack_require__(544); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -77877,7 +77859,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 651 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78223,15 +78205,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 652 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(547); -var toRegex = __webpack_require__(528); -var isOdd = __webpack_require__(653); +var regexNot = __webpack_require__(546); +var toRegex = __webpack_require__(527); +var isOdd = __webpack_require__(652); /** * Characters to use in negation regex (we want to "not" match @@ -78617,7 +78599,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 653 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78630,7 +78612,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(654); +var isNumber = __webpack_require__(653); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -78644,7 +78626,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 654 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78672,14 +78654,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 655 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(656))(); +module.exports = new (__webpack_require__(655))(); /***/ }), -/* 656 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78692,7 +78674,7 @@ module.exports = new (__webpack_require__(656))(); -var MapCache = __webpack_require__(643); +var MapCache = __webpack_require__(642); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -78814,7 +78796,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 657 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78827,14 +78809,14 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(658)(); -var Snapdragon = __webpack_require__(573); -utils.define = __webpack_require__(659); -utils.diff = __webpack_require__(660); -utils.extend = __webpack_require__(649); -utils.pick = __webpack_require__(661); -utils.typeOf = __webpack_require__(662); -utils.unique = __webpack_require__(550); +var isWindows = __webpack_require__(657)(); +var Snapdragon = __webpack_require__(572); +utils.define = __webpack_require__(658); +utils.diff = __webpack_require__(659); +utils.extend = __webpack_require__(648); +utils.pick = __webpack_require__(660); +utils.typeOf = __webpack_require__(661); +utils.unique = __webpack_require__(549); /** * Returns true if the given value is effectively an empty string @@ -79200,7 +79182,7 @@ utils.unixify = function(options) { /***/ }), -/* 658 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -79228,7 +79210,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 659 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79241,8 +79223,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(536); -var isDescriptor = __webpack_require__(537); +var isobject = __webpack_require__(535); +var isDescriptor = __webpack_require__(536); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -79273,7 +79255,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79327,7 +79309,7 @@ function diffArray(one, two) { /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79340,7 +79322,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(536); +var isObject = __webpack_require__(535); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -79369,7 +79351,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -79504,7 +79486,7 @@ function isBuffer(val) { /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79514,18 +79496,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(587); -var unique = __webpack_require__(550); -var toRegex = __webpack_require__(528); +var extend = __webpack_require__(586); +var unique = __webpack_require__(549); +var toRegex = __webpack_require__(527); /** * Local dependencies */ -var compilers = __webpack_require__(664); -var parsers = __webpack_require__(670); -var Extglob = __webpack_require__(673); -var utils = __webpack_require__(672); +var compilers = __webpack_require__(663); +var parsers = __webpack_require__(669); +var Extglob = __webpack_require__(672); +var utils = __webpack_require__(671); var MAX_LENGTH = 1024 * 64; /** @@ -79842,13 +79824,13 @@ module.exports = extglob; /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(665); +var brackets = __webpack_require__(664); /** * Extglob compilers @@ -80018,7 +80000,7 @@ module.exports = function(extglob) { /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80028,17 +80010,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(666); -var parsers = __webpack_require__(668); +var compilers = __webpack_require__(665); +var parsers = __webpack_require__(667); /** * Module dependencies */ -var debug = __webpack_require__(616)('expand-brackets'); -var extend = __webpack_require__(587); -var Snapdragon = __webpack_require__(573); -var toRegex = __webpack_require__(528); +var debug = __webpack_require__(615)('expand-brackets'); +var extend = __webpack_require__(586); +var Snapdragon = __webpack_require__(572); +var toRegex = __webpack_require__(527); /** * Parses the given POSIX character class `pattern` and returns a @@ -80236,13 +80218,13 @@ module.exports = brackets; /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(667); +var posix = __webpack_require__(666); module.exports = function(brackets) { brackets.compiler @@ -80330,7 +80312,7 @@ module.exports = function(brackets) { /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80359,14 +80341,14 @@ module.exports = { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(669); -var define = __webpack_require__(603); +var utils = __webpack_require__(668); +var define = __webpack_require__(602); /** * Text regex @@ -80585,14 +80567,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(528); -var regexNot = __webpack_require__(547); +var toRegex = __webpack_require__(527); +var regexNot = __webpack_require__(546); var cached; /** @@ -80626,15 +80608,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(665); -var define = __webpack_require__(671); -var utils = __webpack_require__(672); +var brackets = __webpack_require__(664); +var define = __webpack_require__(670); +var utils = __webpack_require__(671); /** * Characters to use in text regex (we want to "not" match @@ -80789,7 +80771,7 @@ module.exports = parsers; /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80802,7 +80784,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(537); +var isDescriptor = __webpack_require__(536); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -80827,14 +80809,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(547); -var Cache = __webpack_require__(656); +var regex = __webpack_require__(546); +var Cache = __webpack_require__(655); /** * Utils @@ -80903,7 +80885,7 @@ utils.createRegex = function(str) { /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80913,16 +80895,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(573); -var define = __webpack_require__(671); -var extend = __webpack_require__(587); +var Snapdragon = __webpack_require__(572); +var define = __webpack_require__(670); +var extend = __webpack_require__(586); /** * Local dependencies */ -var compilers = __webpack_require__(664); -var parsers = __webpack_require__(670); +var compilers = __webpack_require__(663); +var parsers = __webpack_require__(669); /** * Customize Snapdragon parser and renderer @@ -80988,16 +80970,16 @@ module.exports = Extglob; /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(663); -var nanomatch = __webpack_require__(648); -var regexNot = __webpack_require__(547); -var toRegex = __webpack_require__(528); +var extglob = __webpack_require__(662); +var nanomatch = __webpack_require__(647); +var regexNot = __webpack_require__(546); +var toRegex = __webpack_require__(527); var not; /** @@ -81078,14 +81060,14 @@ function textRegex(pattern) { /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(656))(); +module.exports = new (__webpack_require__(655))(); /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81098,13 +81080,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(573); -utils.define = __webpack_require__(677); -utils.diff = __webpack_require__(660); -utils.extend = __webpack_require__(645); -utils.pick = __webpack_require__(661); -utils.typeOf = __webpack_require__(678); -utils.unique = __webpack_require__(550); +var Snapdragon = __webpack_require__(572); +utils.define = __webpack_require__(676); +utils.diff = __webpack_require__(659); +utils.extend = __webpack_require__(644); +utils.pick = __webpack_require__(660); +utils.typeOf = __webpack_require__(677); +utils.unique = __webpack_require__(549); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -81401,7 +81383,7 @@ utils.unixify = function(options) { /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81414,8 +81396,8 @@ utils.unixify = function(options) { -var isobject = __webpack_require__(536); -var isDescriptor = __webpack_require__(537); +var isobject = __webpack_require__(535); +var isDescriptor = __webpack_require__(536); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -81446,7 +81428,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -81581,7 +81563,7 @@ function isBuffer(val) { /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81600,9 +81582,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(680); -var reader_1 = __webpack_require__(693); -var fs_stream_1 = __webpack_require__(697); +var readdir = __webpack_require__(679); +var reader_1 = __webpack_require__(692); +var fs_stream_1 = __webpack_require__(696); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -81663,15 +81645,15 @@ exports.default = ReaderAsync; /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(681); -const readdirAsync = __webpack_require__(689); -const readdirStream = __webpack_require__(692); +const readdirSync = __webpack_require__(680); +const readdirAsync = __webpack_require__(688); +const readdirStream = __webpack_require__(691); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -81755,7 +81737,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81763,11 +81745,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(682); +const DirectoryReader = __webpack_require__(681); let syncFacade = { - fs: __webpack_require__(687), - forEach: __webpack_require__(688), + fs: __webpack_require__(686), + forEach: __webpack_require__(687), sync: true }; @@ -81796,7 +81778,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81805,9 +81787,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(138).Readable; const EventEmitter = __webpack_require__(156).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(683); -const stat = __webpack_require__(685); -const call = __webpack_require__(686); +const normalizeOptions = __webpack_require__(682); +const stat = __webpack_require__(684); +const call = __webpack_require__(685); /** * Asynchronously reads the contents of a directory and streams the results @@ -82183,14 +82165,14 @@ module.exports = DirectoryReader; /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(684); +const globToRegExp = __webpack_require__(683); module.exports = normalizeOptions; @@ -82367,7 +82349,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -82504,13 +82486,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(686); +const call = __webpack_require__(685); module.exports = stat; @@ -82585,7 +82567,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82646,14 +82628,14 @@ function callOnce (fn) { /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const call = __webpack_require__(686); +const call = __webpack_require__(685); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -82717,7 +82699,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82746,7 +82728,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82754,12 +82736,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(690); -const DirectoryReader = __webpack_require__(682); +const maybe = __webpack_require__(689); +const DirectoryReader = __webpack_require__(681); let asyncFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(691), + forEach: __webpack_require__(690), async: true }; @@ -82801,7 +82783,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82828,7 +82810,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82864,7 +82846,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82872,11 +82854,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(682); +const DirectoryReader = __webpack_require__(681); let streamFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(691), + forEach: __webpack_require__(690), async: true }; @@ -82896,16 +82878,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(694); -var entry_1 = __webpack_require__(696); -var pathUtil = __webpack_require__(695); +var deep_1 = __webpack_require__(693); +var entry_1 = __webpack_require__(695); +var pathUtil = __webpack_require__(694); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -82971,14 +82953,14 @@ exports.default = Reader; /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(695); -var patternUtils = __webpack_require__(522); +var pathUtils = __webpack_require__(694); +var patternUtils = __webpack_require__(521); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -83061,7 +83043,7 @@ exports.default = DeepFilter; /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83092,14 +83074,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(695); -var patternUtils = __webpack_require__(522); +var pathUtils = __webpack_require__(694); +var patternUtils = __webpack_require__(521); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -83184,7 +83166,7 @@ exports.default = EntryFilter; /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83204,8 +83186,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var fsStat = __webpack_require__(698); -var fs_1 = __webpack_require__(702); +var fsStat = __webpack_require__(697); +var fs_1 = __webpack_require__(701); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -83255,14 +83237,14 @@ exports.default = FileSystemStream; /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(699); -const statProvider = __webpack_require__(701); +const optionsManager = __webpack_require__(698); +const statProvider = __webpack_require__(700); /** * Asynchronous API. */ @@ -83293,13 +83275,13 @@ exports.statSync = statSync; /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(700); +const fsAdapter = __webpack_require__(699); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -83312,7 +83294,7 @@ exports.prepare = prepare; /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83335,7 +83317,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83387,7 +83369,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83418,7 +83400,7 @@ exports.default = FileSystem; /***/ }), -/* 703 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83438,9 +83420,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var readdir = __webpack_require__(680); -var reader_1 = __webpack_require__(693); -var fs_stream_1 = __webpack_require__(697); +var readdir = __webpack_require__(679); +var reader_1 = __webpack_require__(692); +var fs_stream_1 = __webpack_require__(696); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -83508,7 +83490,7 @@ exports.default = ReaderStream; /***/ }), -/* 704 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83527,9 +83509,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(680); -var reader_1 = __webpack_require__(693); -var fs_sync_1 = __webpack_require__(705); +var readdir = __webpack_require__(679); +var reader_1 = __webpack_require__(692); +var fs_sync_1 = __webpack_require__(704); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -83589,7 +83571,7 @@ exports.default = ReaderSync; /***/ }), -/* 705 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83608,8 +83590,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(698); -var fs_1 = __webpack_require__(702); +var fsStat = __webpack_require__(697); +var fs_1 = __webpack_require__(701); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -83655,7 +83637,7 @@ exports.default = FileSystemSync; /***/ }), -/* 706 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83671,7 +83653,7 @@ exports.flatten = flatten; /***/ }), -/* 707 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83692,13 +83674,13 @@ exports.merge = merge; /***/ }), -/* 708 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(709); +const pathType = __webpack_require__(708); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -83764,13 +83746,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 709 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const pify = __webpack_require__(710); +const pify = __webpack_require__(709); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -83813,7 +83795,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 710 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83904,17 +83886,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 711 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(518); -const gitIgnore = __webpack_require__(712); -const pify = __webpack_require__(713); -const slash = __webpack_require__(714); +const fastGlob = __webpack_require__(517); +const gitIgnore = __webpack_require__(711); +const pify = __webpack_require__(712); +const slash = __webpack_require__(713); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -84012,7 +83994,7 @@ module.exports.sync = options => { /***/ }), -/* 712 */ +/* 711 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -84481,7 +84463,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 713 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84556,7 +84538,7 @@ module.exports = (input, options) => { /***/ }), -/* 714 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84574,7 +84556,7 @@ module.exports = input => { /***/ }), -/* 715 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84587,7 +84569,7 @@ module.exports = input => { -var isGlob = __webpack_require__(716); +var isGlob = __webpack_require__(715); module.exports = function hasGlob(val) { if (val == null) return false; @@ -84607,7 +84589,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 716 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -84638,17 +84620,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 717 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); const {constants: fsConstants} = __webpack_require__(134); -const pEvent = __webpack_require__(718); -const CpFileError = __webpack_require__(721); -const fs = __webpack_require__(723); -const ProgressEmitter = __webpack_require__(726); +const pEvent = __webpack_require__(717); +const CpFileError = __webpack_require__(720); +const fs = __webpack_require__(722); +const ProgressEmitter = __webpack_require__(725); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -84762,12 +84744,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 718 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(719); +const pTimeout = __webpack_require__(718); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -85058,12 +85040,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 719 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(720); +const pFinally = __webpack_require__(719); class TimeoutError extends Error { constructor(message) { @@ -85109,7 +85091,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 720 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85131,12 +85113,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 721 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(722); +const NestedError = __webpack_require__(721); class CpFileError extends NestedError { constructor(message, nested) { @@ -85150,7 +85132,7 @@ module.exports = CpFileError; /***/ }), -/* 722 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(112).inherits; @@ -85206,16 +85188,16 @@ module.exports = NestedError; /***/ }), -/* 723 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(112); const fs = __webpack_require__(133); -const makeDir = __webpack_require__(724); -const pEvent = __webpack_require__(718); -const CpFileError = __webpack_require__(721); +const makeDir = __webpack_require__(723); +const pEvent = __webpack_require__(717); +const CpFileError = __webpack_require__(720); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -85312,7 +85294,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 724 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85320,7 +85302,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(134); const path = __webpack_require__(4); const {promisify} = __webpack_require__(112); -const semver = __webpack_require__(725); +const semver = __webpack_require__(724); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -85475,7 +85457,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 725 */ +/* 724 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -87077,7 +87059,7 @@ function coerce (version, options) { /***/ }), -/* 726 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87118,7 +87100,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 727 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87164,12 +87146,12 @@ exports.default = module.exports; /***/ }), -/* 728 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(729); +const pMap = __webpack_require__(728); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -87186,7 +87168,7 @@ module.exports.default = pFilter; /***/ }), -/* 729 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87265,12 +87247,12 @@ module.exports.default = pMap; /***/ }), -/* 730 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(722); +const NestedError = __webpack_require__(721); class CpyError extends NestedError { constructor(message, nested) { diff --git a/src/plugins/runtime_fields/common/constants.ts b/scripts/licenses_csv_report.js similarity index 88% rename from src/plugins/runtime_fields/common/constants.ts rename to scripts/licenses_csv_report.js index 568003508f4bd..6fe813a472745 100644 --- a/src/plugins/runtime_fields/common/constants.ts +++ b/scripts/licenses_csv_report.js @@ -17,4 +17,5 @@ * under the License. */ -export const RUNTIME_FIELD_TYPES = ['keyword', 'long', 'double', 'date', 'ip', 'boolean'] as const; +require('../src/setup_node_env'); +require('../src/dev/run_licenses_csv_report'); diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 12266ec8de2e4..43960ce7db467 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -201,10 +201,13 @@ export class DocLinksService { apiKeyServiceSettings: `${ELASTICSEARCH_DOCS}security-settings.html#api-key-service-settings`, clusterPrivileges: `${ELASTICSEARCH_DOCS}security-privileges.html#privileges-list-cluster`, elasticsearchSettings: `${ELASTICSEARCH_DOCS}security-settings.html`, + elasticsearchEnableSecurity: `${ELASTICSEARCH_DOCS}get-started-enable-security.html`, indicesPrivileges: `${ELASTICSEARCH_DOCS}security-privileges.html#privileges-list-indices`, kibanaTLS: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/configuring-tls.html`, kibanaPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kibana-privileges.html`, mappingRoles: `${ELASTICSEARCH_DOCS}mapping-roles.html`, + mappingRolesFieldRules: `${ELASTICSEARCH_DOCS}role-mapping-resources.html#mapping-roles-rule-field`, + runAsPrivilege: `${ELASTICSEARCH_DOCS}security-privileges.html#_run_as_privilege`, }, watcher: { jiraAction: `${ELASTICSEARCH_DOCS}actions-jira.html`, @@ -219,6 +222,7 @@ export class DocLinksService { createIndex: `${ELASTICSEARCH_DOCS}indices-create-index.html`, createSnapshotLifecylePolicy: `${ELASTICSEARCH_DOCS}slm-api-put-policy.html`, createRoleMapping: `${ELASTICSEARCH_DOCS}security-api-put-role-mapping.html`, + createRoleMappingTemplates: `${ELASTICSEARCH_DOCS}security-api-put-role-mapping.html#_role_templates`, createApiKey: `${ELASTICSEARCH_DOCS}security-api-create-api-key.html`, createPipeline: `${ELASTICSEARCH_DOCS}put-pipeline-api.html`, createTransformRequest: `${ELASTICSEARCH_DOCS}put-transform.html#put-transform-request-body`, diff --git a/src/core/server/http/base_path_proxy_server.test.ts b/src/core/server/http/base_path_proxy_server.test.ts new file mode 100644 index 0000000000000..9f4ffdcf8e081 --- /dev/null +++ b/src/core/server/http/base_path_proxy_server.test.ts @@ -0,0 +1,1052 @@ +/* + * 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 { BasePathProxyServer, BasePathProxyServerOptions } from './base_path_proxy_server'; +import { loggingSystemMock } from '../logging/logging_system.mock'; +import { DevConfig } from '../dev/dev_config'; +import { EMPTY } from 'rxjs'; +import { HttpConfig } from './http_config'; +import { ByteSizeValue, schema } from '@kbn/config-schema'; +import { + KibanaRequest, + KibanaResponseFactory, + Router, + RouteValidationFunction, + RouteValidationResultFactory, +} from './router'; +import { HttpServer } from './http_server'; +import supertest from 'supertest'; +import { RequestHandlerContext } from 'kibana/server'; +import { readFileSync } from 'fs'; +import { KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; +import { omit } from 'lodash'; +import { Readable } from 'stream'; + +/** + * Most of these tests are inspired by: + * src/core/server/http/http_server.test.ts + * and copied for completeness from that file. The modifications are that these tests use the developer proxy. + */ +describe('BasePathProxyServer', () => { + let server: HttpServer; + let proxyServer: BasePathProxyServer; + let config: HttpConfig; + let configWithSSL: HttpConfig; + let basePath: string; + let certificate: string; + let key: string; + let proxySupertest: supertest.SuperTest; + const logger = loggingSystemMock.createLogger(); + const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); + + beforeAll(() => { + certificate = readFileSync(KBN_CERT_PATH, 'utf8'); + key = readFileSync(KBN_KEY_PATH, 'utf8'); + }); + + beforeEach(async () => { + // setup the server but don't start it until each individual test so that routes can be dynamically configured per unit test. + server = new HttpServer(logger, 'tests'); + config = ({ + name: 'kibana', + host: '127.0.0.1', + port: 10012, + compression: { enabled: true }, + requestId: { + allowFromAnyIp: true, + ipAllowlist: [], + }, + autoListen: true, + keepaliveTimeout: 1000, + socketTimeout: 1000, + cors: { + enabled: false, + allowCredentials: false, + allowOrigin: [], + }, + ssl: { enabled: false }, + customResponseHeaders: {}, + maxPayload: new ByteSizeValue(1024), + rewriteBasePath: true, + } as unknown) as HttpConfig; + + configWithSSL = { + ...config, + ssl: { + enabled: true, + certificate, + cipherSuites: ['TLS_AES_256_GCM_SHA384'], + getSecureOptions: () => 0, + key, + redirectHttpFromPort: config.port + 1, + }, + } as HttpConfig; + + // setup and start the proxy server + const proxyConfig: HttpConfig = { ...config, port: 10013 }; + const devConfig = new DevConfig({ basePathProxyTarget: config.port }); + proxyServer = new BasePathProxyServer(logger, proxyConfig, devConfig); + const options: Readonly = { + shouldRedirectFromOldBasePath: () => true, + delayUntil: () => EMPTY, + }; + await proxyServer.start(options); + + // set the base path or throw if for some unknown reason it is not setup + if (proxyServer.basePath == null) { + throw new Error('Invalid null base path, all tests will fail'); + } else { + basePath = proxyServer.basePath; + } + proxySupertest = supertest(`http://127.0.0.1:${proxyConfig.port}`); + }); + + afterEach(async () => { + await server.stop(); + await proxyServer.stop(); + jest.clearAllMocks(); + }); + + test('root URL will return a 302 redirect', async () => { + await proxySupertest.get('/').expect(302); + }); + + test('root URL will return a redirect location with exactly 3 characters that are a-z', async () => { + const res = await proxySupertest.get('/'); + const location = res.header.location; + expect(location).toMatch(/[a-z]{3}/); + }); + + test('valid params', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + router.get( + { + path: '/{test}', + validate: { + params: schema.object({ + test: schema.string(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.params.test }); + } + ); + const { registerRouter } = await server.setup(config); + registerRouter(router); + await server.start(); + + await proxySupertest + .get(`${basePath}/foo/some-string`) + .expect(200) + .then((res) => { + expect(res.text).toBe('some-string'); + }); + }); + + test('invalid params', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.get( + { + path: '/{test}', + validate: { + params: schema.object({ + test: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: String(req.params.test) }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .get(`${basePath}/foo/some-string`) + .expect(400) + .then((res) => { + expect(res.body).toEqual({ + error: 'Bad Request', + statusCode: 400, + message: '[request params.test]: expected value of type [number] but got [string]', + }); + }); + }); + + test('valid query', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.get( + { + path: '/', + validate: { + query: schema.object({ + bar: schema.string(), + quux: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.query }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .get(`${basePath}/foo/?bar=test&quux=123`) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'test', quux: 123 }); + }); + }); + + test('invalid query', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.get( + { + path: '/', + validate: { + query: schema.object({ + bar: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.query }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .get(`${basePath}/foo/?bar=test`) + .expect(400) + .then((res) => { + expect(res.body).toEqual({ + error: 'Bad Request', + statusCode: 400, + message: '[request query.bar]: expected value of type [number] but got [string]', + }); + }); + }); + + test('valid body', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.post( + { + path: '/', + validate: { + body: schema.object({ + bar: schema.string(), + baz: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ + bar: 'test', + baz: 123, + }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'test', baz: 123 }); + }); + }); + + test('valid body with validate function', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.post( + { + path: '/', + validate: { + body: ({ bar, baz } = {}, { ok, badRequest }) => { + if (typeof bar === 'string' && typeof baz === 'number') { + return ok({ bar, baz }); + } else { + return badRequest('Wrong payload', ['body']); + } + }, + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ + bar: 'test', + baz: 123, + }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'test', baz: 123 }); + }); + }); + + test('not inline validation - specifying params', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + const bodyValidation = ( + { bar, baz }: any = {}, + { ok, badRequest }: RouteValidationResultFactory + ) => { + if (typeof bar === 'string' && typeof baz === 'number') { + return ok({ bar, baz }); + } else { + return badRequest('Wrong payload', ['body']); + } + }; + + router.post( + { + path: '/', + validate: { + body: bodyValidation, + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ + bar: 'test', + baz: 123, + }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'test', baz: 123 }); + }); + }); + + test('not inline validation - specifying validation handler', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + const bodyValidation: RouteValidationFunction<{ bar: string; baz: number }> = ( + { bar, baz } = {}, + { ok, badRequest } + ) => { + if (typeof bar === 'string' && typeof baz === 'number') { + return ok({ bar, baz }); + } else { + return badRequest('Wrong payload', ['body']); + } + }; + + router.post( + { + path: '/', + validate: { + body: bodyValidation, + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ + bar: 'test', + baz: 123, + }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'test', baz: 123 }); + }); + }); + + test('not inline handler - KibanaRequest', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + const handler = ( + context: RequestHandlerContext, + req: KibanaRequest, + res: KibanaResponseFactory + ) => { + const body = { + bar: req.body.bar.toUpperCase(), + baz: req.body.baz.toString(), + }; + + return res.ok({ body }); + }; + + router.post( + { + path: '/', + validate: { + body: ({ bar, baz } = {}, { ok, badRequest }) => { + if (typeof bar === 'string' && typeof baz === 'number') { + return ok({ bar, baz }); + } else { + return badRequest('Wrong payload', ['body']); + } + }, + }, + }, + handler + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ + bar: 'test', + baz: 123, + }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ bar: 'TEST', baz: '123' }); + }); + }); + + test('invalid body', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.post( + { + path: '/', + validate: { + body: schema.object({ + bar: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .post(`${basePath}/foo/`) + .send({ bar: 'test' }) + .expect(400) + .then((res) => { + expect(res.body).toEqual({ + error: 'Bad Request', + statusCode: 400, + message: '[request body.bar]: expected value of type [number] but got [string]', + }); + }); + }); + + test('handles putting', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.put( + { + path: '/', + validate: { + body: schema.object({ + key: schema.string(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: req.body }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .put(`${basePath}/foo/`) + .send({ key: 'new value' }) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ key: 'new value' }); + }); + }); + + test('handles deleting', async () => { + const router = new Router(`${basePath}/foo`, logger, enhanceWithContext); + + router.delete( + { + path: '/{id}', + validate: { + params: schema.object({ + id: schema.number(), + }), + }, + }, + (_, req, res) => { + return res.ok({ body: { key: req.params.id } }); + } + ); + + const { registerRouter } = await server.setup(config); + registerRouter(router); + + await server.start(); + + await proxySupertest + .delete(`${basePath}/foo/3`) + .expect(200) + .then((res) => { + expect(res.body).toEqual({ key: 3 }); + }); + }); + + describe('with `basepath: /bar` and `rewriteBasePath: false`', () => { + let configWithBasePath: HttpConfig; + + beforeEach(async () => { + configWithBasePath = { + ...config, + basePath: '/bar', + rewriteBasePath: false, + } as HttpConfig; + + const router = new Router(`${basePath}/`, logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (_, __, res) => res.ok({ body: 'value:/' })); + router.get({ path: '/foo', validate: false }, (_, __, res) => res.ok({ body: 'value:/foo' })); + + const { registerRouter } = await server.setup(configWithBasePath); + registerRouter(router); + + await server.start(); + }); + + test('/bar => 404', async () => { + await proxySupertest.get(`${basePath}/bar`).expect(404); + }); + + test('/bar/ => 404', async () => { + await proxySupertest.get(`${basePath}/bar/`).expect(404); + }); + + test('/bar/foo => 404', async () => { + await proxySupertest.get(`${basePath}/bar/foo`).expect(404); + }); + + test('/ => /', async () => { + await proxySupertest + .get(`${basePath}/`) + .expect(200) + .then((res) => { + expect(res.text).toBe('value:/'); + }); + }); + + test('/foo => /foo', async () => { + await proxySupertest + .get(`${basePath}/foo`) + .expect(200) + .then((res) => { + expect(res.text).toBe('value:/foo'); + }); + }); + }); + + test('with defined `redirectHttpFromPort`', async () => { + const router = new Router(`${basePath}/`, logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (_, __, res) => res.ok({ body: 'value:/' })); + + const { registerRouter } = await server.setup(configWithSSL); + registerRouter(router); + + await server.start(); + }); + + test('allows attaching metadata to attach meta-data tag strings to a route', async () => { + const tags = ['my:tag']; + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.get({ path: '/with-tags', validate: false, options: { tags } }, (_, req, res) => + res.ok({ body: { tags: req.route.options.tags } }) + ); + router.get({ path: '/without-tags', validate: false }, (_, req, res) => + res.ok({ body: { tags: req.route.options.tags } }) + ); + registerRouter(router); + + await server.start(); + await proxySupertest.get(`${basePath}/with-tags`).expect(200, { tags }); + + await proxySupertest.get(`${basePath}/without-tags`).expect(200, { tags: [] }); + }); + + describe('response headers', () => { + test('default headers', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (_, req, res) => res.ok({ body: req.route })); + registerRouter(router); + + await server.start(); + const response = await proxySupertest.get(`${basePath}/`).expect(200); + + const restHeaders = omit(response.header, ['date', 'content-length']); + expect(restHeaders).toMatchInlineSnapshot(` + Object { + "accept-ranges": "bytes", + "cache-control": "private, no-cache, no-store, must-revalidate", + "connection": "close", + "content-type": "application/json; charset=utf-8", + } + `); + }); + }); + + test('exposes route details of incoming request to a route handler (POST + payload options)', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.post( + { + path: '/', + validate: { body: schema.object({ test: schema.number() }) }, + options: { body: { accepts: 'application/json' } }, + }, + (_, req, res) => res.ok({ body: req.route }) + ); + registerRouter(router); + + await server.start(); + await proxySupertest + .post(`${basePath}/`) + .send({ test: 1 }) + .expect(200, { + method: 'post', + path: `${basePath}/`, + options: { + authRequired: true, + xsrfRequired: true, + tags: [], + timeout: { + payload: 10000, + idleSocket: 1000, + }, + body: { + parse: true, // hapi populates the default + maxBytes: 1024, // hapi populates the default + accepts: ['application/json'], + output: 'data', + }, + }, + }); + }); + + test('should return a stream in the body', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.put( + { + path: '/', + validate: { body: schema.stream() }, + options: { body: { output: 'stream' } }, + }, + (_, req, res) => { + try { + expect(req.body).toBeInstanceOf(Readable); + return res.ok({ body: req.route.options.body }); + } catch (err) { + return res.internalError({ body: err.message }); + } + } + ); + registerRouter(router); + + await server.start(); + await proxySupertest.put(`${basePath}/`).send({ test: 1 }).expect(200, { + parse: true, + maxBytes: 1024, // hapi populates the default + output: 'stream', + }); + }); + + describe('timeout options', () => { + describe('payload timeout', () => { + test('POST routes set the payload timeout', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.post( + { + path: '/', + validate: false, + options: { + timeout: { + payload: 300000, + }, + }, + }, + (_, req, res) => { + try { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } catch (err) { + return res.internalError({ body: err.message }); + } + } + ); + registerRouter(router); + await server.start(); + await proxySupertest + .post(`${basePath}/`) + .send({ test: 1 }) + .expect(200, { + timeout: { + payload: 300000, + idleSocket: 1000, // This is an extra option added by the proxy + }, + }); + }); + + test('DELETE routes set the payload timeout', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.delete( + { + path: '/', + validate: false, + options: { + timeout: { + payload: 300000, + }, + }, + }, + (context, req, res) => { + try { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } catch (err) { + return res.internalError({ body: err.message }); + } + } + ); + registerRouter(router); + await server.start(); + await proxySupertest.delete(`${basePath}/`).expect(200, { + timeout: { + payload: 300000, + idleSocket: 1000, // This is an extra option added by the proxy + }, + }); + }); + + test('PUT routes set the payload timeout and automatically adjusts the idle socket timeout', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.put( + { + path: '/', + validate: false, + options: { + timeout: { + payload: 300000, + }, + }, + }, + (_, req, res) => { + try { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } catch (err) { + return res.internalError({ body: err.message }); + } + } + ); + registerRouter(router); + await server.start(); + await proxySupertest.put(`${basePath}/`).expect(200, { + timeout: { + payload: 300000, + idleSocket: 1000, // This is an extra option added by the proxy + }, + }); + }); + + test('PATCH routes set the payload timeout and automatically adjusts the idle socket timeout', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.patch( + { + path: '/', + validate: false, + options: { + timeout: { + payload: 300000, + }, + }, + }, + (_, req, res) => { + try { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } catch (err) { + return res.internalError({ body: err.message }); + } + } + ); + registerRouter(router); + await server.start(); + await proxySupertest.patch(`${basePath}/`).expect(200, { + timeout: { + payload: 300000, + idleSocket: 1000, // This is an extra option added by the proxy + }, + }); + }); + }); + + describe('idleSocket timeout', () => { + test('uses server socket timeout when not specified in the route', async () => { + const { registerRouter } = await server.setup({ + ...config, + socketTimeout: 11000, + }); + + const router = new Router(basePath, logger, enhanceWithContext); + router.get( + { + path: '/', + validate: { body: schema.maybe(schema.any()) }, + }, + (_, req, res) => { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } + ); + registerRouter(router); + + await server.start(); + await proxySupertest + .get(`${basePath}/`) + .send() + .expect(200, { + timeout: { + idleSocket: 11000, + }, + }); + }); + + test('sets the socket timeout when specified in the route', async () => { + const { registerRouter } = await server.setup({ + ...config, + socketTimeout: 11000, + }); + + const router = new Router(basePath, logger, enhanceWithContext); + router.get( + { + path: '/', + validate: { body: schema.maybe(schema.any()) }, + options: { timeout: { idleSocket: 12000 } }, + }, + (context, req, res) => { + return res.ok({ + body: { + timeout: req.route.options.timeout, + }, + }); + } + ); + registerRouter(router); + + await server.start(); + await proxySupertest + .get(`${basePath}/`) + .send() + .expect(200, { + timeout: { + idleSocket: 12000, + }, + }); + }); + + test('idleSocket timeout can be smaller than the payload timeout', async () => { + const { registerRouter } = await server.setup(config); + + const router = new Router(basePath, logger, enhanceWithContext); + router.post( + { + path: `${basePath}/`, + validate: { body: schema.any() }, + options: { + timeout: { + payload: 1000, + idleSocket: 10, + }, + }, + }, + (_, req, res) => { + return res.ok({ body: { timeout: req.route.options.timeout } }); + } + ); + + registerRouter(router); + + await server.start(); + }); + }); + }); + + describe('shouldRedirect', () => { + let proxyServerWithoutShouldRedirect: BasePathProxyServer; + let proxyWithoutShouldRedirectSupertest: supertest.SuperTest; + + beforeEach(async () => { + // setup and start a proxy server which does not use "shouldRedirectFromOldBasePath" + const proxyConfig: HttpConfig = { ...config, port: 10004 }; + const devConfig = new DevConfig({ basePathProxyTarget: config.port }); + proxyServerWithoutShouldRedirect = new BasePathProxyServer(logger, proxyConfig, devConfig); + const options: Readonly = { + shouldRedirectFromOldBasePath: () => false, // Return false to not redirect + delayUntil: () => EMPTY, + }; + await proxyServerWithoutShouldRedirect.start(options); + proxyWithoutShouldRedirectSupertest = supertest(`http://127.0.0.1:${proxyConfig.port}`); + }); + + afterEach(async () => { + await proxyServerWithoutShouldRedirect.stop(); + }); + + test('it will do a redirect if it detects what looks like a stale or previously used base path', async () => { + const fakeBasePath = basePath !== 'abc' ? 'abc' : 'efg'; + const res = await proxySupertest.get(`/${fakeBasePath}`).expect(302); + const location = res.header.location; + expect(location).toEqual(`${basePath}/`); + }); + + test('it will NOT do a redirect if it detects what looks like a stale or previously used base path if we intentionally turn it off', async () => { + const fakeBasePath = basePath !== 'abc' ? 'abc' : 'efg'; + await proxyWithoutShouldRedirectSupertest.get(`/${fakeBasePath}`).expect(404); + }); + + test('it will NOT redirect if it detects a larger path than 3 characters', async () => { + await proxySupertest.get('/abcde').expect(404); + }); + + test('it will NOT redirect if it is not a GET verb', async () => { + const fakeBasePath = basePath !== 'abc' ? 'abc' : 'efg'; + await proxySupertest.put(`/${fakeBasePath}`).expect(404); + }); + }); + + describe('constructor option for sending in a custom basePath', () => { + let proxyServerWithFooBasePath: BasePathProxyServer; + let proxyWithFooBasePath: supertest.SuperTest; + + beforeEach(async () => { + // setup and start a proxy server which uses a basePath of "foo" + const proxyConfig: HttpConfig = { ...config, port: 10004, basePath: '/foo' }; // <-- "foo" here in basePath + const devConfig = new DevConfig({ basePathProxyTarget: config.port }); + proxyServerWithFooBasePath = new BasePathProxyServer(logger, proxyConfig, devConfig); + const options: Readonly = { + shouldRedirectFromOldBasePath: () => true, + delayUntil: () => EMPTY, + }; + await proxyServerWithFooBasePath.start(options); + proxyWithFooBasePath = supertest(`http://127.0.0.1:${proxyConfig.port}`); + }); + + afterEach(async () => { + await proxyServerWithFooBasePath.stop(); + }); + + test('it will do a redirect to foo which is our passed in value for the configuration', async () => { + const res = await proxyWithFooBasePath.get('/bar').expect(302); + const location = res.header.location; + expect(location).toEqual('/foo/'); + }); + }); +}); diff --git a/src/core/server/http/base_path_proxy_server.ts b/src/core/server/http/base_path_proxy_server.ts index d461abe54ccbd..dfcd0757c2d1e 100644 --- a/src/core/server/http/base_path_proxy_server.ts +++ b/src/core/server/http/base_path_proxy_server.ts @@ -143,12 +143,25 @@ export class BasePathProxyServer { handler: { proxy: { agent: this.httpsAgent, - host: this.server.info.host, passThrough: true, - port: this.devConfig.basePathProxyTargetPort, - // typings mismatch. h2o2 doesn't support "socket" - protocol: this.server.info.protocol as HapiProxy.ProxyHandlerOptions['protocol'], xforward: true, + mapUri: async (request) => { + return { + // Passing in this header to merge it is a workaround until this is fixed: + // https://github.com/hapijs/h2o2/issues/124 + headers: + request.headers['content-length'] != null + ? { 'content-length': request.headers['content-length'] } + : undefined, + uri: Url.format({ + hostname: request.server.info.host, + port: this.devConfig.basePathProxyTargetPort, + protocol: request.server.info.protocol, + pathname: request.path, + query: request.query, + }), + }; + }, }, }, method: '*', diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index cbb60480c4cf1..70c346a5333cc 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -888,52 +888,48 @@ describe('conditional compression', () => { expect(response.header).not.toHaveProperty('content-encoding'); }); }); +}); - describe('response headers', () => { - it('allows to configure "keep-alive" header', async () => { - const { registerRouter, server: innerServer } = await server.setup({ - ...config, - keepaliveTimeout: 100_000, - }); +describe('response headers', () => { + test('allows to configure "keep-alive" header', async () => { + const { registerRouter, server: innerServer } = await server.setup({ + ...config, + keepaliveTimeout: 100_000, + }); - const router = new Router('', logger, enhanceWithContext); - router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ body: req.route }) - ); - registerRouter(router); + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: req.route })); + registerRouter(router); - await server.start(); - const response = await supertest(innerServer.listener) - .get('/') - .set('Connection', 'keep-alive') - .expect(200); + await server.start(); + const response = await supertest(innerServer.listener) + .get('/') + .set('Connection', 'keep-alive') + .expect(200); - expect(response.header.connection).toBe('keep-alive'); - expect(response.header['keep-alive']).toBe('timeout=100'); - }); + expect(response.header.connection).toBe('keep-alive'); + expect(response.header['keep-alive']).toBe('timeout=100'); + }); - it('default headers', async () => { - const { registerRouter, server: innerServer } = await server.setup(config); + test('default headers', async () => { + const { registerRouter, server: innerServer } = await server.setup(config); - const router = new Router('', logger, enhanceWithContext); - router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ body: req.route }) - ); - registerRouter(router); + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: req.route })); + registerRouter(router); - await server.start(); - const response = await supertest(innerServer.listener).get('/').expect(200); - - const restHeaders = omit(response.header, ['date', 'content-length']); - expect(restHeaders).toMatchInlineSnapshot(` - Object { - "accept-ranges": "bytes", - "cache-control": "private, no-cache, no-store, must-revalidate", - "connection": "close", - "content-type": "application/json; charset=utf-8", - } - `); - }); + await server.start(); + const response = await supertest(innerServer.listener).get('/').expect(200); + + const restHeaders = omit(response.header, ['date', 'content-length']); + expect(restHeaders).toMatchInlineSnapshot(` + Object { + "accept-ranges": "bytes", + "cache-control": "private, no-cache, no-store, must-revalidate", + "connection": "close", + "content-type": "application/json; charset=utf-8", + } + `); }); }); @@ -1270,31 +1266,31 @@ describe('timeout options', () => { }, }); }); - }); - test(`idleSocket timeout can be smaller than the payload timeout`, async () => { - const { registerRouter } = await server.setup(config); + test('idleSocket timeout can be smaller than the payload timeout', async () => { + const { registerRouter } = await server.setup(config); - const router = new Router('', logger, enhanceWithContext); - router.post( - { - path: '/', - validate: { body: schema.any() }, - options: { - timeout: { - payload: 1000, - idleSocket: 10, + const router = new Router('', logger, enhanceWithContext); + router.post( + { + path: '/', + validate: { body: schema.any() }, + options: { + timeout: { + payload: 1000, + idleSocket: 10, + }, }, }, - }, - (context, req, res) => { - return res.ok({ body: { timeout: req.route.options.timeout } }); - } - ); + (context, req, res) => { + return res.ok({ body: { timeout: req.route.options.timeout } }); + } + ); - registerRouter(router); + registerRouter(router); - await server.start(); + await server.start(); + }); }); }); @@ -1329,13 +1325,14 @@ test('should return a stream in the body', async () => { describe('setup contract', () => { describe('#createSessionStorage', () => { - it('creates session storage factory', async () => { + test('creates session storage factory', async () => { const { createCookieSessionStorageFactory } = await server.setup(config); const sessionStorageFactory = await createCookieSessionStorageFactory(cookieOptions); expect(sessionStorageFactory.asScoped).toBeDefined(); }); - it('creates session storage factory only once', async () => { + + test('creates session storage factory only once', async () => { const { createCookieSessionStorageFactory } = await server.setup(config); const create = async () => await createCookieSessionStorageFactory(cookieOptions); @@ -1343,7 +1340,7 @@ describe('setup contract', () => { expect(create()).rejects.toThrowError('A cookieSessionStorageFactory was already created'); }); - it('does not throw if called after stop', async () => { + test('does not throw if called after stop', async () => { const { createCookieSessionStorageFactory } = await server.setup(config); await server.stop(); expect(() => { @@ -1353,7 +1350,7 @@ describe('setup contract', () => { }); describe('#getServerInfo', () => { - it('returns correct information', async () => { + test('returns correct information', async () => { let { getServerInfo } = await server.setup(config); expect(getServerInfo()).toEqual({ @@ -1378,7 +1375,7 @@ describe('setup contract', () => { }); }); - it('returns correct protocol when ssl is enabled', async () => { + test('returns correct protocol when ssl is enabled', async () => { const { getServerInfo } = await server.setup(configWithSSL); expect(getServerInfo().protocol).toEqual('https'); @@ -1386,7 +1383,7 @@ describe('setup contract', () => { }); describe('#registerStaticDir', () => { - it('does not throw if called after stop', async () => { + test('does not throw if called after stop', async () => { const { registerStaticDir } = await server.setup(config); await server.stop(); expect(() => { diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts index abda7cf82b121..1fd2e7352d8f7 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/actions.test.ts @@ -908,8 +908,7 @@ describe('migration actions', () => { }); }); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/87160 - describe.skip('createIndex', () => { + describe('createIndex', () => { afterAll(async () => { await client.indices.delete({ index: 'yellow_then_green_index' }); }); @@ -936,6 +935,7 @@ describe('migration actions', () => { setTimeout(() => { client.indices.putSettings({ + index: 'yellow_then_green_index', body: { index: { number_of_replicas: 0, diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/migration.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/migration.test.ts index 942021fd1918d..723f4c02db3ce 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/migration.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/migration.test.ts @@ -127,7 +127,8 @@ describe('migration v2', () => { await new Promise((resolve) => setTimeout(resolve, 10000)); }; - describe('migrating from 7.3.0-xpack version', () => { + // FLAKY: https://github.com/elastic/kibana/issues/87968 + describe.skip('migrating from 7.3.0-xpack version', () => { const migratedIndex = `.kibana_${kibanaVersion}_001`; beforeAll(async () => { diff --git a/src/dev/code_coverage/shell_scripts/copy_mocha_reports.sh b/src/dev/code_coverage/shell_scripts/copy_mocha_reports.sh deleted file mode 100644 index 579276aac990f..0000000000000 --- a/src/dev/code_coverage/shell_scripts/copy_mocha_reports.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -EXTRACT_START_DIR=tmp/extracted_coverage -EXTRACT_END_DIR=target/kibana-coverage -COMBINED_EXRACT_DIR=/${EXTRACT_START_DIR}/${EXTRACT_END_DIR} - - -echo "### Copy mocha reports" -mkdir -p $EXTRACT_END_DIR/mocha-combined -cp -r $COMBINED_EXRACT_DIR/mocha/. $EXTRACT_END_DIR/mocha-combined/ diff --git a/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh index 62b81929ae79b..caa1f1a761367 100644 --- a/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh +++ b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh @@ -40,11 +40,5 @@ for x in jest functional; do node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH done -# Need to override COVERAGE_INGESTION_KIBANA_ROOT since mocha json file has original intake worker path -COVERAGE_SUMMARY_FILE=target/kibana-coverage/mocha-combined/coverage-summary.json -export COVERAGE_INGESTION_KIBANA_ROOT=/dev/shm/workspace/kibana - -node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH - echo "### Ingesting Code Coverage - Complete" echo "" diff --git a/src/dev/run_find_plugins_with_circular_deps.ts b/src/dev/run_find_plugins_with_circular_deps.ts index 75faf3d8c17a7..fc599ad738dfa 100644 --- a/src/dev/run_find_plugins_with_circular_deps.ts +++ b/src/dev/run_find_plugins_with_circular_deps.ts @@ -31,7 +31,6 @@ interface Options { type CircularDepList = Set; const allowedList: CircularDepList = new Set([ - 'src/plugins/visualizations -> src/plugins/visualize', 'x-pack/plugins/actions -> x-pack/plugins/case', 'x-pack/plugins/case -> x-pack/plugins/security_solution', 'x-pack/plugins/apm -> x-pack/plugins/infra', diff --git a/src/dev/run_licenses_csv_report.js b/src/dev/run_licenses_csv_report.js new file mode 100644 index 0000000000000..791f296085deb --- /dev/null +++ b/src/dev/run_licenses_csv_report.js @@ -0,0 +1,128 @@ +/* + * 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 { writeFileSync } from 'fs'; +import { resolve } from 'path'; +import { isNull, isUndefined } from 'lodash'; + +import { run } from '@kbn/dev-utils'; + +import { getInstalledPackages } from './npm'; +import { engines } from '../../package'; +import { LICENSE_OVERRIDES } from './license_checker'; + +const allDoubleQuoteRE = /"/g; + +function escapeValue(value) { + if (isNull(value)) { + return; + } + + return `"${value.replace(allDoubleQuoteRE, '""')}"`; +} + +function formatCsvValues(fields, values) { + return fields + .map((field) => { + const value = values[field]; + + if (isNull(value) || isUndefined(value)) { + return null; + } + + return value.toString(); + }) + .map(escapeValue) + .join(','); +} + +run( + async ({ log, flags }) => { + const fields = ['name', 'version', 'url', 'license', 'sourceURL']; + + const file = flags.csv; + const directory = flags.directory; + const dev = flags.dev; + + const root = resolve(__dirname, '..', '..'); + const packages = await getInstalledPackages({ + directory: directory ? resolve(directory) : root, + licenseOverrides: LICENSE_OVERRIDES, + dev, + }); + + packages.unshift( + { + name: 'Node.js', + version: engines.node, + repository: 'https://nodejs.org', + licenses: ['MIT'], + }, + { + name: 'Red Hat Universal Base Image minimal', + version: '8', + repository: + 'https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/5c359a62bed8bd75a2c3fba8', + licenses: [ + 'Custom;https://www.redhat.com/licenses/EULA_Red_Hat_Universal_Base_Image_English_20190422.pdf', + ], + sourceURL: 'https://oss-dependencies.elastic.co/redhat/ubi/ubi-minimal-8-source.tar.gz', + } + ); + + const csv = packages + .map((pkg) => { + const data = { + name: pkg.name, + version: pkg.version, + url: pkg.repository || `https://www.npmjs.com/package/${pkg.name}`, + license: pkg.licenses.join(','), + sourceURL: pkg.sourceURL, + }; + + return formatCsvValues(fields, data); + }) + .join('\n'); + + if (file) { + writeFileSync(file, `${fields.join(',')}\n${csv}`); + log.success(`wrote to ${file}`); + } else { + log.success(csv); + log.debug('\nspecify "--csv [filepath]" to write the data to a specific file'); + } + }, + { + description: ` + Report of 3rd party dependencies + `, + flags: { + boolean: ['dev'], + string: ['csv', 'directory'], + default: { + dev: false, + }, + help: ` + --dev Include development dependencies + --csv Write csv report to file + --directory Directory to check for licenses + `, + }, + } +); diff --git a/src/plugins/advanced_settings/tsconfig.json b/src/plugins/advanced_settings/tsconfig.json new file mode 100644 index 0000000000000..4d62e410326b6 --- /dev/null +++ b/src/plugins/advanced_settings/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../management/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + ] +} diff --git a/src/plugins/charts/tsconfig.json b/src/plugins/charts/tsconfig.json new file mode 100644 index 0000000000000..a4f65d5937204 --- /dev/null +++ b/src/plugins/charts/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../embeddable/tsconfig.json" } + ] +} diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx index abef8afcc3985..4abc37a455d05 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -97,6 +97,7 @@ function EditorUI({ initialTextValue }: EditorProps) { if (textareaElement) { textareaElement.setAttribute('id', inputId); + textareaElement.setAttribute('data-test-subj', 'console-textarea'); } const readQueryParams = () => { @@ -204,7 +205,7 @@ function EditorUI({ initialTextValue }: EditorProps) { }, [sendCurrentRequestToES, openDocumentation]); return ( -
+
    { }; }); +// @ts-ignore import { EuiObserver } from '@elastic/eui/test-env/components/observer/observer'; jest.mock('@elastic/eui/test-env/components/observer/observer'); EuiObserver.mockImplementation(() => 'EuiObserver'); diff --git a/src/plugins/dashboard/kibana.json b/src/plugins/dashboard/kibana.json index b5451203e2365..e074d529917d2 100644 --- a/src/plugins/dashboard/kibana.json +++ b/src/plugins/dashboard/kibana.json @@ -6,14 +6,21 @@ "embeddable", "inspector", "kibanaLegacy", - "urlForwarding", "navigation", - "uiActions", "savedObjects", - "share" + "share", + "uiActions", + "urlForwarding" ], - "optionalPlugins": ["home", "usageCollection", "savedObjectsTaggingOss"], + "optionalPlugins": [ + "home", + "savedObjectsTaggingOss", + "usageCollection"], "server": true, "ui": true, - "requiredBundles": ["kibanaUtils", "kibanaReact", "home"] + "requiredBundles": [ + "home", + "kibanaReact", + "kibanaUtils" + ] } diff --git a/src/plugins/dashboard/public/application/dashboard_app.tsx b/src/plugins/dashboard/public/application/dashboard_app.tsx index f33383427342b..8f4bc8bc6ef1a 100644 --- a/src/plugins/dashboard/public/application/dashboard_app.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app.tsx @@ -173,10 +173,14 @@ export function DashboardApp({ ).subscribe(() => refreshDashboardContainer()) ); subscriptions.add( - data.search.session.onRefresh$.subscribe(() => { + merge( + data.search.session.onRefresh$, + data.query.timefilter.timefilter.getAutoRefreshFetch$() + ).subscribe(() => { setLastReloadTime(() => new Date().getTime()); }) ); + dashboardStateManager.registerChangeListener(() => { // we aren't checking dirty state because there are changes the container needs to know about // that won't make the dashboard "dirty" - like a view mode change. diff --git a/src/plugins/dashboard/public/application/dashboard_state.test.ts b/src/plugins/dashboard/public/application/dashboard_state.test.ts index f31ed30f8eb80..ddfca1eddcc19 100644 --- a/src/plugins/dashboard/public/application/dashboard_state.test.ts +++ b/src/plugins/dashboard/public/application/dashboard_state.test.ts @@ -19,11 +19,11 @@ import { createBrowserHistory } from 'history'; import { getSavedDashboardMock } from './test_helpers'; -import { DashboardContainer, DashboardContainerInput } from '.'; +import { DashboardContainer, DashboardContainerInput, DashboardPanelState } from '.'; import { DashboardStateManager } from './dashboard_state_manager'; import { DashboardContainerServices } from './embeddable/dashboard_container'; -import { ViewMode } from '../services/embeddable'; +import { EmbeddableInput, ViewMode } from '../services/embeddable'; import { createKbnUrlStateStorage } from '../services/kibana_utils'; import { InputTimeRange, TimefilterContract, TimeRange } from '../services/data'; @@ -134,6 +134,11 @@ describe('DashboardState', function () { const dashboardContainer = initDashboardContainer({ expandedPanelId: 'theCoolestPanelOnThisDashboard', + panels: { + theCoolestPanelOnThisDashboard: { + explicitInput: { id: 'theCoolestPanelOnThisDashboard' }, + } as DashboardPanelState, + }, }); dashboardState.handleDashboardContainerChanges(dashboardContainer); @@ -149,15 +154,39 @@ describe('DashboardState', function () { const dashboardContainer = initDashboardContainer({ expandedPanelId: 'theCoolestPanelOnThisDashboard', + panels: { + theCoolestPanelOnThisDashboard: { + explicitInput: { id: 'theCoolestPanelOnThisDashboard' }, + } as DashboardPanelState, + }, }); dashboardState.handleDashboardContainerChanges(dashboardContainer); dashboardState.handleDashboardContainerChanges(dashboardContainer); expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(1); + }); + + test('expandedPanelId is set to undefined if panel does not exist in input', () => { + dashboardState.setExpandedPanelId = jest + .fn() + .mockImplementation(dashboardState.setExpandedPanelId); + const dashboardContainer = initDashboardContainer({ + expandedPanelId: 'theCoolestPanelOnThisDashboard', + panels: { + theCoolestPanelOnThisDashboard: { + explicitInput: { id: 'theCoolestPanelOnThisDashboard' }, + } as DashboardPanelState, + }, + }); + + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledWith( + 'theCoolestPanelOnThisDashboard' + ); - dashboardContainer.updateInput({ expandedPanelId: 'woah it changed' }); + dashboardContainer.updateInput({ expandedPanelId: 'theLeastCoolPanelOnThisDashboard' }); dashboardState.handleDashboardContainerChanges(dashboardContainer); - expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(2); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledWith(undefined); }); }); diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts index dfcbfcafd3db1..891add08547db 100644 --- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts @@ -223,6 +223,7 @@ export class DashboardStateManager { const savedDashboardPanelMap: { [key: string]: SavedDashboardPanel } = {}; const input = dashboardContainer.getInput(); + this.getPanels().forEach((savedDashboardPanel) => { if (input.panels[savedDashboardPanel.panelIndex] !== undefined) { savedDashboardPanelMap[savedDashboardPanel.panelIndex] = savedDashboardPanel; @@ -234,11 +235,16 @@ export class DashboardStateManager { const convertedPanelStateMap: { [key: string]: SavedDashboardPanel } = {}; + let expandedPanelValid = false; Object.values(input.panels).forEach((panelState) => { if (savedDashboardPanelMap[panelState.explicitInput.id] === undefined) { dirty = true; } + if (panelState.explicitInput.id === input.expandedPanelId) { + expandedPanelValid = true; + } + convertedPanelStateMap[panelState.explicitInput.id] = convertPanelStateToSavedDashboardPanel( panelState, this.kibanaVersion @@ -272,8 +278,10 @@ export class DashboardStateManager { this.setFullScreenMode(input.isFullScreenMode); } - if (input.expandedPanelId !== this.getExpandedPanelId()) { + if (expandedPanelValid && input.expandedPanelId !== this.getExpandedPanelId()) { this.setExpandedPanelId(input.expandedPanelId); + } else if (!expandedPanelValid && this.getExpandedPanelId()) { + this.setExpandedPanelId(undefined); } if (!_.isEqual(input.query, this.getQuery())) { diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx index c5929c5d85dbb..3d7b9312a5127 100644 --- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx +++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx @@ -34,7 +34,6 @@ import { ViewMode, EmbeddableChildPanel } from '../../../services/embeddable'; import { DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT } from '../dashboard_constants'; import { DashboardPanelState } from '../types'; import { withKibana } from '../../../services/kibana_react'; -import { DashboardContainerInput } from '../dashboard_container'; import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container'; let lastValidGridSize = 0; @@ -177,18 +176,17 @@ class DashboardGridUi extends React.Component { isLayoutInvalid, }); - this.subscription = this.props.container - .getInput$() - .subscribe((input: DashboardContainerInput) => { - if (this.mounted) { - this.setState({ - panels: input.panels, - viewMode: input.viewMode, - useMargins: input.useMargins, - expandedPanelId: input.expandedPanelId, - }); - } - }); + this.subscription = this.props.container.getInput$().subscribe(() => { + const { panels, viewMode, useMargins, expandedPanelId } = this.props.container.getInput(); + if (this.mounted) { + this.setState({ + panels, + viewMode, + useMargins, + expandedPanelId, + }); + } + }); } public componentWillUnmount() { diff --git a/src/plugins/dashboard/public/application/lib/session_restoration.ts b/src/plugins/dashboard/public/application/lib/session_restoration.ts index 5f05fa122e161..890b81b5418be 100644 --- a/src/plugins/dashboard/public/application/lib/session_restoration.ts +++ b/src/plugins/dashboard/public/application/lib/session_restoration.ts @@ -43,17 +43,22 @@ function getUrlGeneratorState({ data, getAppState, getDashboardId, - forceAbsoluteTime, // TODO: not implemented + forceAbsoluteTime, }: { data: DataPublicPluginStart; getAppState: () => DashboardAppState; getDashboardId: () => string; + /** + * Can force time range from time filter to convert from relative to absolute time range + */ forceAbsoluteTime: boolean; }): DashboardUrlGeneratorState { const appState = getAppState(); return { dashboardId: getDashboardId(), - timeRange: data.query.timefilter.timefilter.getTime(), + timeRange: forceAbsoluteTime + ? data.query.timefilter.timefilter.getAbsoluteTime() + : data.query.timefilter.timefilter.getTime(), filters: data.query.filterManager.getFilters(), query: data.query.queryString.formatQuery(appState.query), savedQuery: appState.savedQuery, diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json new file mode 100644 index 0000000000000..c70f2bad7e701 --- /dev/null +++ b/src/plugins/dashboard/tsconfig.json @@ -0,0 +1,34 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "*.ts", + ".storybook/**/*", + "common/**/*", + "public/**/*", + "server/**/*", + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../inspector/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../share/tsconfig.json" }, + { "path": "../url_forwarding/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../data/tsconfig.json"}, + { "path": "../embeddable/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../navigation/tsconfig.json" }, + { "path": "../saved_objects_tagging_oss/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + { "path": "../ui_actions/tsconfig.json" }, + ] +} diff --git a/src/plugins/data/common/query/timefilter/get_time.test.ts b/src/plugins/data/common/query/timefilter/get_time.test.ts index 4dba157a6f554..5b77153136761 100644 --- a/src/plugins/data/common/query/timefilter/get_time.test.ts +++ b/src/plugins/data/common/query/timefilter/get_time.test.ts @@ -19,7 +19,7 @@ import moment from 'moment'; import sinon from 'sinon'; -import { getTime } from './get_time'; +import { getTime, getAbsoluteTimeRange } from './get_time'; describe('get_time', () => { describe('getTime', () => { @@ -90,4 +90,19 @@ describe('get_time', () => { clock.restore(); }); }); + describe('getAbsoluteTimeRange', () => { + test('should forward absolute timerange as is', () => { + const from = '2000-01-01T00:00:00.000Z'; + const to = '2000-02-01T00:00:00.000Z'; + expect(getAbsoluteTimeRange({ from, to })).toEqual({ from, to }); + }); + + test('should convert relative to absolute', () => { + const clock = sinon.useFakeTimers(moment.utc([2000, 1, 0, 0, 0, 0, 0]).valueOf()); + const from = '2000-01-01T00:00:00.000Z'; + const to = moment.utc(clock.now).toISOString(); + expect(getAbsoluteTimeRange({ from, to: 'now' })).toEqual({ from, to }); + clock.restore(); + }); + }); }); diff --git a/src/plugins/data/common/query/timefilter/get_time.ts b/src/plugins/data/common/query/timefilter/get_time.ts index 6e4eda95accc7..bb7b5760240b7 100644 --- a/src/plugins/data/common/query/timefilter/get_time.ts +++ b/src/plugins/data/common/query/timefilter/get_time.ts @@ -34,6 +34,17 @@ export function calculateBounds( }; } +export function getAbsoluteTimeRange( + timeRange: TimeRange, + { forceNow }: { forceNow?: Date } = {} +): TimeRange { + const { min, max } = calculateBounds(timeRange, { forceNow }); + return { + from: min ? min.toISOString() : timeRange.from, + to: max ? max.toISOString() : timeRange.to, + }; +} + export function getTime( indexPattern: IIndexPattern | undefined, timeRange: TimeRange, diff --git a/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.test.ts index bd3c4f8dd58cf..5edbf6fc4eac2 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.test.ts @@ -108,13 +108,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.ts b/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.ts index 3e3895b7b50db..55a43864879c4 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_histogram_fn.ts @@ -152,7 +152,6 @@ export const aggDateHistogram = (): FunctionDefinition => ({ ...rest, timeRange: getParsedValue(args, 'timeRange'), extended_bounds: getParsedValue(args, 'extended_bounds'), - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/date_range_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/date_range_fn.test.ts index 93bb791874e67..2aa6a3a1f6fab 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_range_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_range_fn.test.ts @@ -88,14 +88,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'date_field', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/date_range_fn.ts b/src/plugins/data/common/search/aggs/buckets/date_range_fn.ts index 0dc66be5b84f2..c09c87b8b9afd 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_range_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_range_fn.ts @@ -107,7 +107,6 @@ export const aggDateRange = (): FunctionDefinition => ({ type: BUCKET_TYPES.DATE_RANGE, params: { ...rest, - json: getParsedValue(args, 'json'), ranges: getParsedValue(args, 'ranges'), }, }, diff --git a/src/plugins/data/common/search/aggs/buckets/filter_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/filter_fn.test.ts index c820a73b0a894..1d85b7dba8bd1 100644 --- a/src/plugins/data/common/search/aggs/buckets/filter_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/filter_fn.test.ts @@ -73,13 +73,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/filter_fn.ts b/src/plugins/data/common/search/aggs/buckets/filter_fn.ts index 8c8c0f430184a..07ed11e2249b1 100644 --- a/src/plugins/data/common/search/aggs/buckets/filter_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/filter_fn.ts @@ -95,7 +95,6 @@ export const aggFilter = (): FunctionDefinition => ({ type: BUCKET_TYPES.FILTER, params: { ...rest, - json: getParsedValue(args, 'json'), geo_bounding_box: getParsedValue(args, 'geo_bounding_box'), }, }, diff --git a/src/plugins/data/common/search/aggs/buckets/filters_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/filters_fn.test.ts index 99c4f7d8c2b65..da29afec1e1e6 100644 --- a/src/plugins/data/common/search/aggs/buckets/filters_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/filters_fn.test.ts @@ -79,13 +79,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/filters_fn.ts b/src/plugins/data/common/search/aggs/buckets/filters_fn.ts index 194feb67d3366..ccf9232d14d3f 100644 --- a/src/plugins/data/common/search/aggs/buckets/filters_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/filters_fn.ts @@ -90,7 +90,6 @@ export const aggFilters = (): FunctionDefinition => ({ params: { ...rest, filters: getParsedValue(args, 'filters'), - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.test.ts index 07ab8e66f1def..1fbb69d7dd182 100644 --- a/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.test.ts @@ -99,14 +99,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'geo_field', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.ts b/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.ts index aa5f473f73f9d..cbd901a438eb4 100644 --- a/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/geo_hash_fn.ts @@ -126,7 +126,6 @@ export const aggGeoHash = (): FunctionDefinition => ({ params: { ...rest, boundingBox: getParsedValue(args, 'boundingBox'), - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.test.ts index bfaf47ede8734..78bf16e8f067c 100644 --- a/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.test.ts @@ -78,14 +78,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'geo_field', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.ts b/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.ts index 346c70bba31fd..1e7258ea7da53 100644 --- a/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/geo_tile_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, BUCKET_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggGeoTileFnName = 'aggGeoTile'; @@ -105,7 +104,6 @@ export const aggGeoTile = (): FunctionDefinition => ({ type: BUCKET_TYPES.GEOTILE_GRID, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/histogram_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/histogram_fn.test.ts index 354946f99a2f5..4a8e785da2974 100644 --- a/src/plugins/data/common/search/aggs/buckets/histogram_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/histogram_fn.test.ts @@ -98,15 +98,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'field', - interval: '10', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/histogram_fn.ts b/src/plugins/data/common/search/aggs/buckets/histogram_fn.ts index 62dbc7ca8ca45..6b5e2d02b271b 100644 --- a/src/plugins/data/common/search/aggs/buckets/histogram_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/histogram_fn.ts @@ -135,7 +135,6 @@ export const aggHistogram = (): FunctionDefinition => ({ params: { ...rest, extended_bounds: getParsedValue(args, 'extended_bounds'), - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/ip_range_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/ip_range_fn.test.ts index 5940345b25890..462672cf5dffe 100644 --- a/src/plugins/data/common/search/aggs/buckets/ip_range_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/ip_range_fn.test.ts @@ -88,15 +88,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'ip_field', - ipRangeType: IP_RANGE_TYPES.FROM_TO, - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/ip_range_fn.ts b/src/plugins/data/common/search/aggs/buckets/ip_range_fn.ts index 7ad61a9c27d86..92eedc35ce61b 100644 --- a/src/plugins/data/common/search/aggs/buckets/ip_range_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/ip_range_fn.ts @@ -110,7 +110,6 @@ export const aggIpRange = (): FunctionDefinition => ({ type: BUCKET_TYPES.IP_RANGE, params: { ...rest, - json: getParsedValue(args, 'json'), ranges: getParsedValue(args, 'ranges'), }, }, diff --git a/src/plugins/data/common/search/aggs/buckets/range_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/range_fn.test.ts index 93ae4490196a8..1a08cc1adaa28 100644 --- a/src/plugins/data/common/search/aggs/buckets/range_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/range_fn.test.ts @@ -87,14 +87,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - field: 'number_field', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/range_fn.ts b/src/plugins/data/common/search/aggs/buckets/range_fn.ts index a52b2427b9845..f3d662ced8fcf 100644 --- a/src/plugins/data/common/search/aggs/buckets/range_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/range_fn.ts @@ -102,7 +102,6 @@ export const aggRange = (): FunctionDefinition => ({ type: BUCKET_TYPES.RANGE, params: { ...rest, - json: getParsedValue(args, 'json'), ranges: getParsedValue(args, 'ranges'), }, }, diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts index 89281490167b3..d2c1fc77d0514 100644 --- a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts @@ -52,14 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - - expect(() => { - fn({ - delay: '1000ms', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts index 87f80192ca3cd..d13138ad43dad 100644 --- a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggConfigSerialized } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; import { AggParamsShardDelay, SHARD_DELAY_AGG_NAME } from './shard_delay'; export const aggShardDelayFnName = 'aggShardDelay'; @@ -93,7 +92,6 @@ export const aggShardDelay = (): FunctionDefinition => ({ type: SHARD_DELAY_AGG_NAME, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.test.ts index 71be4e9cfa9ac..9e94654821913 100644 --- a/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.test.ts @@ -84,13 +84,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.ts b/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.ts index a1a7500678fd6..2998200ccae76 100644 --- a/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/significant_terms_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, BUCKET_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggSignificantTermsFnName = 'aggSignificantTerms'; @@ -113,7 +112,6 @@ export const aggSignificantTerms = (): FunctionDefinition => ({ type: BUCKET_TYPES.SIGNIFICANT_TERMS, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/buckets/terms_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/terms_fn.test.ts index 1384a9f17e4b6..9374497ddb664 100644 --- a/src/plugins/data/common/search/aggs/buckets/terms_fn.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/terms_fn.test.ts @@ -154,15 +154,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - order: 'asc', - orderBy: '1', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/buckets/terms_fn.ts b/src/plugins/data/common/search/aggs/buckets/terms_fn.ts index 7737cb1e1c952..a0b491b4cb398 100644 --- a/src/plugins/data/common/search/aggs/buckets/terms_fn.ts +++ b/src/plugins/data/common/search/aggs/buckets/terms_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, BUCKET_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggTermsFnName = 'aggTerms'; @@ -160,7 +159,6 @@ export const aggTerms = (): FunctionDefinition => ({ params: { ...rest, orderAgg: args.orderAgg?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/avg_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/avg_fn.test.ts index 0e2ee00df49dd..8162b6e7554f0 100644 --- a/src/plugins/data/common/search/aggs/metrics/avg_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/avg_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/avg_fn.ts b/src/plugins/data/common/search/aggs/metrics/avg_fn.ts index 57dd3dae70fba..d28bd88095191 100644 --- a/src/plugins/data/common/search/aggs/metrics/avg_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/avg_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggAvgFnName = 'aggAvg'; @@ -87,7 +86,6 @@ export const aggAvg = (): FunctionDefinition => ({ type: METRIC_TYPES.AVG, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.test.ts index 7e08bc9954510..7329ea57ade83 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.test.ts @@ -67,12 +67,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.ts b/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.ts index 595d49647d9c2..cfed0205f1b61 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_avg_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggBucketAvgFnName = 'aggBucketAvg'; @@ -104,7 +103,6 @@ export const aggBucketAvg = (): FunctionDefinition => ({ ...rest, customBucket: args.customBucket?.value, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.test.ts index b789bdf51ebd5..9e890331a848f 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.test.ts @@ -67,12 +67,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.ts b/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.ts index 482c73e7d3005..90a494f8cbc77 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_max_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggBucketMaxFnName = 'aggBucketMax'; @@ -104,7 +103,6 @@ export const aggBucketMax = (): FunctionDefinition => ({ ...rest, customBucket: args.customBucket?.value, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.test.ts index 6ebc83417813b..8a03849769a9a 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.test.ts @@ -67,12 +67,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.ts b/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.ts index 68beffbf05660..8f48166887f25 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_min_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggBucketMinFnName = 'aggBucketMin'; @@ -104,7 +103,6 @@ export const aggBucketMin = (): FunctionDefinition => ({ ...rest, customBucket: args.customBucket?.value, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.test.ts index 71549f41b1d15..ea26f58dd2f15 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.test.ts @@ -67,12 +67,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.ts b/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.ts index 7994bb85be2a7..d26f22b106c2f 100644 --- a/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/bucket_sum_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggBucketSumFnName = 'aggBucketSum'; @@ -104,7 +103,6 @@ export const aggBucketSum = (): FunctionDefinition => ({ ...rest, customBucket: args.customBucket?.value, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/cardinality_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/cardinality_fn.test.ts index 4008819018ee5..5045fccf921a3 100644 --- a/src/plugins/data/common/search/aggs/metrics/cardinality_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/cardinality_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/cardinality_fn.ts b/src/plugins/data/common/search/aggs/metrics/cardinality_fn.ts index 6e78a42fea90f..e5599ab8599f7 100644 --- a/src/plugins/data/common/search/aggs/metrics/cardinality_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/cardinality_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggCardinalityFnName = 'aggCardinality'; @@ -92,7 +91,6 @@ export const aggCardinality = (): FunctionDefinition => ({ type: METRIC_TYPES.CARDINALITY, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.test.ts index 3cf53e3da153e..48120f9bdc338 100644 --- a/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.test.ts @@ -108,13 +108,7 @@ describe('agg_expression_functions', () => { buckets_path: 'the_sum', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - buckets_path: 'the_sum', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.ts b/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.ts index 040e26125079f..b20d03f06c854 100644 --- a/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/cumulative_sum_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggCumulativeSumFnName = 'aggCumulativeSum'; @@ -107,7 +106,6 @@ export const aggCumulativeSum = (): FunctionDefinition => ({ params: { ...rest, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/derivative_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/derivative_fn.test.ts index 79ea7292104ee..602ef8e1de48b 100644 --- a/src/plugins/data/common/search/aggs/metrics/derivative_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/derivative_fn.test.ts @@ -108,13 +108,7 @@ describe('agg_expression_functions', () => { buckets_path: 'the_sum', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - buckets_path: 'the_sum', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/derivative_fn.ts b/src/plugins/data/common/search/aggs/metrics/derivative_fn.ts index 93ef0286a0c7e..b3fb448446c44 100644 --- a/src/plugins/data/common/search/aggs/metrics/derivative_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/derivative_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggDerivativeFnName = 'aggDerivative'; @@ -107,7 +106,6 @@ export const aggDerivative = (): FunctionDefinition => ({ params: { ...rest, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.test.ts index 96bd31916784a..3f85a874b0dd5 100644 --- a/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.ts b/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.ts index af5ea3c80506c..1403d95371c1d 100644 --- a/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/geo_bounds_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggGeoBoundsFnName = 'aggGeoBounds'; @@ -92,7 +91,6 @@ export const aggGeoBounds = (): FunctionDefinition => ({ type: METRIC_TYPES.GEO_BOUNDS, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.test.ts index bf9a4548bafbf..aea6ee1f2c332 100644 --- a/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.ts b/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.ts index 2c2d60711def3..9e36e07cbaf58 100644 --- a/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/geo_centroid_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggGeoCentroidFnName = 'aggGeoCentroid'; @@ -92,7 +91,6 @@ export const aggGeoCentroid = (): FunctionDefinition => ({ type: METRIC_TYPES.GEO_CENTROID, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/max_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/max_fn.test.ts index 156b51ca54af5..b042b82a048c2 100644 --- a/src/plugins/data/common/search/aggs/metrics/max_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/max_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/max_fn.ts b/src/plugins/data/common/search/aggs/metrics/max_fn.ts index 9624cd3012398..7f1e3b9ad9d69 100644 --- a/src/plugins/data/common/search/aggs/metrics/max_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/max_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggMaxFnName = 'aggMax'; @@ -87,7 +86,6 @@ export const aggMax = (): FunctionDefinition => ({ type: METRIC_TYPES.MAX, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/median_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/median_fn.test.ts index 69200c35426c8..def9197bc3444 100644 --- a/src/plugins/data/common/search/aggs/metrics/median_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/median_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/median_fn.ts b/src/plugins/data/common/search/aggs/metrics/median_fn.ts index e2ea8ae0fe2e7..2323fa969c245 100644 --- a/src/plugins/data/common/search/aggs/metrics/median_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/median_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggMedianFnName = 'aggMedian'; @@ -92,7 +91,6 @@ export const aggMedian = (): FunctionDefinition => ({ type: METRIC_TYPES.MEDIAN, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/min_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/min_fn.test.ts index ef32d086e41f7..44d0f0f4f4607 100644 --- a/src/plugins/data/common/search/aggs/metrics/min_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/min_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/min_fn.ts b/src/plugins/data/common/search/aggs/metrics/min_fn.ts index b880937eea2d7..40b2085a97e97 100644 --- a/src/plugins/data/common/search/aggs/metrics/min_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/min_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggMinFnName = 'aggMin'; @@ -87,7 +86,6 @@ export const aggMin = (): FunctionDefinition => ({ type: METRIC_TYPES.MIN, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.test.ts index d6c0e6b2cbd6e..a9334480ec602 100644 --- a/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.test.ts @@ -118,13 +118,7 @@ describe('agg_expression_functions', () => { buckets_path: 'the_sum', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - buckets_path: 'the_sum', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.ts b/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.ts index 85b7e536e66fc..5f30e088954c9 100644 --- a/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/moving_avg_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggMovingAvgFnName = 'aggMovingAvg'; @@ -120,7 +119,6 @@ export const aggMovingAvg = (): FunctionDefinition => ({ params: { ...rest, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.test.ts index e3ce91bafd40a..c9393f68ce404 100644 --- a/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.test.ts @@ -81,13 +81,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.ts b/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.ts index 9bf35c4dba9ff..bd4c83c1bdbbb 100644 --- a/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/percentile_ranks_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggPercentileRanksFnName = 'aggPercentileRanks'; @@ -99,7 +98,6 @@ export const aggPercentileRanks = (): FunctionDefinition => ({ type: METRIC_TYPES.PERCENTILE_RANKS, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/percentiles_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/percentiles_fn.test.ts index 2074cc1d89527..4b8424b79b33a 100644 --- a/src/plugins/data/common/search/aggs/metrics/percentiles_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/percentiles_fn.test.ts @@ -81,13 +81,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/percentiles_fn.ts b/src/plugins/data/common/search/aggs/metrics/percentiles_fn.ts index d7bcefc23f711..0b5f5d4c1a890 100644 --- a/src/plugins/data/common/search/aggs/metrics/percentiles_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/percentiles_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggPercentilesFnName = 'aggPercentiles'; @@ -99,7 +98,6 @@ export const aggPercentiles = (): FunctionDefinition => ({ type: METRIC_TYPES.PERCENTILES, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.test.ts index 1bb859ad4bad8..a3410401a38cf 100644 --- a/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.test.ts @@ -108,13 +108,7 @@ describe('agg_expression_functions', () => { buckets_path: 'the_sum', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - json: '/// intentionally malformed json ///', - buckets_path: 'the_sum', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.ts b/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.ts index f3602f5519d5e..f2c5b152e2f2f 100644 --- a/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/serial_diff_fn.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggSerialDiffFnName = 'aggSerialDiff'; @@ -107,7 +106,6 @@ export const aggSerialDiff = (): FunctionDefinition => ({ params: { ...rest, customMetric: args.customMetric?.value, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.test.ts index bfa6aa7cc4122..bbaa1d3eef3fc 100644 --- a/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.ts b/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.ts index 2a3c1bd33e17d..d0dadf7e0078e 100644 --- a/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/std_deviation_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggStdDeviationFnName = 'aggStdDeviation'; @@ -92,7 +91,6 @@ export const aggStdDeviation = (): FunctionDefinition => ({ type: METRIC_TYPES.STD_DEV, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/sum_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/sum_fn.test.ts index 6e57632ba84cc..fed56246e087a 100644 --- a/src/plugins/data/common/search/aggs/metrics/sum_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/sum_fn.test.ts @@ -52,13 +52,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/sum_fn.ts b/src/plugins/data/common/search/aggs/metrics/sum_fn.ts index a42510dc594ad..d58231f732c9d 100644 --- a/src/plugins/data/common/search/aggs/metrics/sum_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/sum_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggSumFnName = 'aggSum'; @@ -87,7 +86,6 @@ export const aggSum = (): FunctionDefinition => ({ type: METRIC_TYPES.SUM, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/aggs/metrics/top_hit_fn.test.ts b/src/plugins/data/common/search/aggs/metrics/top_hit_fn.test.ts index d0e9788f85025..7251909e44c81 100644 --- a/src/plugins/data/common/search/aggs/metrics/top_hit_fn.test.ts +++ b/src/plugins/data/common/search/aggs/metrics/top_hit_fn.test.ts @@ -89,14 +89,7 @@ describe('agg_expression_functions', () => { json: '{ "foo": true }', }); - expect(actual.value.params.json).toEqual({ foo: true }); - expect(() => { - fn({ - field: 'machine.os.keyword', - aggregate: 'min', - json: '/// intentionally malformed json ///', - }); - }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + expect(actual.value.params.json).toEqual('{ "foo": true }'); }); }); }); diff --git a/src/plugins/data/common/search/aggs/metrics/top_hit_fn.ts b/src/plugins/data/common/search/aggs/metrics/top_hit_fn.ts index 38a3bc6a59bfc..2636e9865df18 100644 --- a/src/plugins/data/common/search/aggs/metrics/top_hit_fn.ts +++ b/src/plugins/data/common/search/aggs/metrics/top_hit_fn.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; -import { getParsedValue } from '../utils/get_parsed_value'; export const aggTopHitFnName = 'aggTopHit'; @@ -119,7 +118,6 @@ export const aggTopHit = (): FunctionDefinition => ({ type: METRIC_TYPES.TOP_HITS, params: { ...rest, - json: getParsedValue(args, 'json'), }, }, }; diff --git a/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts b/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts index 2274fcfd6b8d5..e9bf03af192ba 100644 --- a/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts +++ b/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts @@ -62,6 +62,7 @@ export interface EsaggsStartDependencies { deserializeFieldFormat: FormatFactory; indexPatterns: IndexPatternsContract; searchSource: ISearchStartSearchSource; + getNow?: () => Date; } /** @internal */ @@ -118,7 +119,8 @@ export async function handleEsaggsRequest( args: Arguments, params: RequestHandlerParams ): Promise { - const resolvedTimeRange = input?.timeRange && calculateBounds(input.timeRange); + const resolvedTimeRange = + input?.timeRange && calculateBounds(input.timeRange, { forceNow: params.getNow?.() }); const response = await handleRequest(params); diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index b773aad67c3f8..29a841b18706c 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -51,6 +51,7 @@ export interface RequestHandlerParams { searchSourceService: ISearchStartSearchSource; timeFields?: string[]; timeRange?: TimeRange; + getNow?: () => Date; } export const handleRequest = async ({ @@ -67,7 +68,9 @@ export const handleRequest = async ({ searchSourceService, timeFields, timeRange, + getNow, }: RequestHandlerParams) => { + const forceNow = getNow?.(); const searchSource = await searchSourceService.create(); searchSource.setField('index', indexPattern); @@ -115,7 +118,7 @@ export const handleRequest = async ({ if (timeRange && allTimeFields.length > 0) { timeFilterSearchSource.setField('filter', () => { return allTimeFields - .map((fieldName) => getTime(indexPattern, timeRange, { fieldName })) + .map((fieldName) => getTime(indexPattern, timeRange, { fieldName, forceNow })) .filter(isRangeFilter); }); } @@ -183,7 +186,7 @@ export const handleRequest = async ({ } } - const parsedTimeRange = timeRange ? calculateBounds(timeRange) : null; + const parsedTimeRange = timeRange ? calculateBounds(timeRange, { forceNow }) : null; const tabifyParams = { metricsAtAllLevels, partialRows, diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 67c1ff7e09dd7..c34139caa553e 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -22,6 +22,7 @@ import { fieldFormatsServiceMock } from './field_formats/mocks'; import { searchServiceMock } from './search/mocks'; import { queryServiceMock } from './query/mocks'; import { AutocompleteStart, AutocompleteSetup } from './autocomplete'; +import { createNowProviderMock } from './now_provider/mocks'; export type Setup = jest.Mocked>; export type Start = jest.Mocked>; @@ -76,6 +77,7 @@ const createStartContract = (): Start => { get: jest.fn().mockReturnValue(Promise.resolve({})), clearCache: jest.fn(), } as unknown) as IndexPatternsContract, + nowProvider: createNowProviderMock(), }; }; diff --git a/src/plugins/runtime_fields/public/index.ts b/src/plugins/data/public/now_provider/index.ts similarity index 86% rename from src/plugins/runtime_fields/public/index.ts rename to src/plugins/data/public/now_provider/index.ts index a7a94b07ac6e8..662ab87dd534b 100644 --- a/src/plugins/runtime_fields/public/index.ts +++ b/src/plugins/data/public/now_provider/index.ts @@ -17,12 +17,8 @@ * under the License. */ -export * from '../common'; - -export function plugin() { - return { - setup() {}, - start() {}, - stop() {}, - }; -} +export { + NowProvider, + NowProviderInternalContract, + NowProviderPublicContract, +} from './now_provider'; diff --git a/src/plugins/data/public/now_provider/lib/get_force_now_from_url.test.ts b/src/plugins/data/public/now_provider/lib/get_force_now_from_url.test.ts new file mode 100644 index 0000000000000..4e3233474b040 --- /dev/null +++ b/src/plugins/data/public/now_provider/lib/get_force_now_from_url.test.ts @@ -0,0 +1,50 @@ +/* + * 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 { getForceNowFromUrl } from './get_force_now_from_url'; +const originalLocation = window.location; +afterAll(() => { + window.location = originalLocation; +}); + +function mockLocation(url: string) { + // @ts-ignore + delete window.location; + // @ts-ignore + window.location = new URL(url); +} + +test('should get force now from URL', () => { + const dateString = '1999-01-01T00:00:00.000Z'; + mockLocation(`https://elastic.co/?forceNow=${dateString}`); + + expect(getForceNowFromUrl()).toEqual(new Date(dateString)); +}); + +test('should throw if force now is invalid', () => { + const dateString = 'invalid-date'; + mockLocation(`https://elastic.co/?forceNow=${dateString}`); + + expect(() => getForceNowFromUrl()).toThrowError(); +}); + +test('should return undefined if no forceNow', () => { + mockLocation(`https://elastic.co/`); + expect(getForceNowFromUrl()).toBe(undefined); +}); diff --git a/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts b/src/plugins/data/public/now_provider/lib/get_force_now_from_url.ts similarity index 74% rename from src/plugins/data/public/query/timefilter/lib/parse_querystring.ts rename to src/plugins/data/public/now_provider/lib/get_force_now_from_url.ts index 5982bfd0bd276..906eec1ab143e 100644 --- a/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts +++ b/src/plugins/data/public/now_provider/lib/get_force_now_from_url.ts @@ -16,10 +16,25 @@ * specific language governing permissions and limitations * under the License. */ + import { parse } from 'query-string'; /** @internal */ -export function parseQueryString() { +export function getForceNowFromUrl(): Date | undefined { + const forceNow = parseQueryString().forceNow as string; + if (!forceNow) { + return; + } + + const ts = Date.parse(forceNow); + if (isNaN(ts)) { + throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`); + } + return new Date(ts); +} + +/** @internal */ +function parseQueryString() { // window.location.search is an empty string // get search from href const hrefSplit = window.location.href.split('?'); diff --git a/src/plugins/data/public/now_provider/lib/index.ts b/src/plugins/data/public/now_provider/lib/index.ts new file mode 100644 index 0000000000000..990db5ae3c77c --- /dev/null +++ b/src/plugins/data/public/now_provider/lib/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 { getForceNowFromUrl } from './get_force_now_from_url'; diff --git a/src/plugins/runtime_fields/common/types.ts b/src/plugins/data/public/now_provider/mocks.ts similarity index 76% rename from src/plugins/runtime_fields/common/types.ts rename to src/plugins/data/public/now_provider/mocks.ts index f16d3d75d6ecf..1021d2b48cfe5 100644 --- a/src/plugins/runtime_fields/common/types.ts +++ b/src/plugins/data/public/now_provider/mocks.ts @@ -17,13 +17,12 @@ * under the License. */ -import { RUNTIME_FIELD_TYPES } from './constants'; +import { NowProviderInternalContract } from './now_provider'; -export type RuntimeType = typeof RUNTIME_FIELD_TYPES[number]; -export interface RuntimeField { - name: string; - type: RuntimeType; - script: { - source: string; +export const createNowProviderMock = (): jest.Mocked => { + return { + get: jest.fn(() => new Date()), + set: jest.fn(), + reset: jest.fn(), }; -} +}; diff --git a/src/plugins/data/public/now_provider/now_provider.test.ts b/src/plugins/data/public/now_provider/now_provider.test.ts new file mode 100644 index 0000000000000..e557065ff2b67 --- /dev/null +++ b/src/plugins/data/public/now_provider/now_provider.test.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { NowProvider, NowProviderInternalContract } from './now_provider'; + +let mockDateFromUrl: undefined | Date; +let nowProvider: NowProviderInternalContract; + +jest.mock('./lib', () => ({ + // @ts-ignore + ...jest.requireActual('./lib'), + getForceNowFromUrl: () => mockDateFromUrl, +})); + +beforeEach(() => { + nowProvider = new NowProvider(); +}); +afterEach(() => { + mockDateFromUrl = undefined; +}); + +test('should return Date.now() by default', async () => { + const now = Date.now(); + await new Promise((r) => setTimeout(r, 10)); + expect(nowProvider.get().getTime()).toBeGreaterThan(now); +}); + +test('should forceNow from URL', async () => { + mockDateFromUrl = new Date('1999-01-01T00:00:00.000Z'); + nowProvider = new NowProvider(); + expect(nowProvider.get()).toEqual(mockDateFromUrl); +}); + +test('should forceNow from URL if custom now is set', async () => { + mockDateFromUrl = new Date('1999-01-01T00:00:00.000Z'); + nowProvider = new NowProvider(); + nowProvider.set(new Date()); + expect(nowProvider.get()).toEqual(mockDateFromUrl); +}); diff --git a/src/plugins/data/public/now_provider/now_provider.ts b/src/plugins/data/public/now_provider/now_provider.ts new file mode 100644 index 0000000000000..a55fa691ef1da --- /dev/null +++ b/src/plugins/data/public/now_provider/now_provider.ts @@ -0,0 +1,50 @@ +/* + * 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 { PublicMethodsOf } from '@kbn/utility-types'; +import { getForceNowFromUrl } from './lib'; + +export type NowProviderInternalContract = PublicMethodsOf; +export type NowProviderPublicContract = Pick; + +/** + * Used to synchronize time between parallel searches with relative time range that rely on `now`. + */ +export class NowProvider { + // TODO: service shouldn't access params in the URL + // instead it should be handled by apps + private readonly nowFromUrl = getForceNowFromUrl(); + private now?: Date; + + constructor() {} + + get(): Date { + if (this.nowFromUrl) return this.nowFromUrl; // now forced from URL always takes precedence + if (this.now) return this.now; + return new Date(); + } + + set(now: Date) { + this.now = now; + } + + reset() { + this.now = undefined; + } +} diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 43abe84950fdb..aabf3136e6159 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -61,6 +61,7 @@ import { SavedObjectsClientPublicToCommon } from './index_patterns'; import { getIndexPatternLoad } from './index_patterns/expressions'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { getTableViewDescription } from './utils/table_inspector_view'; +import { NowProvider, NowProviderInternalContract } from './now_provider'; export class DataPublicPlugin implements @@ -76,6 +77,7 @@ export class DataPublicPlugin private readonly queryService: QueryService; private readonly storage: IStorageWrapper; private usageCollection: UsageCollectionSetup | undefined; + private readonly nowProvider: NowProviderInternalContract; constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(initializerContext); @@ -83,6 +85,7 @@ export class DataPublicPlugin this.fieldFormatsService = new FieldFormatsService(); this.autocomplete = new AutocompleteService(initializerContext); this.storage = new Storage(window.localStorage); + this.nowProvider = new NowProvider(); } public setup( @@ -95,9 +98,17 @@ export class DataPublicPlugin this.usageCollection = usageCollection; + const searchService = this.searchService.setup(core, { + bfetch, + usageCollection, + expressions, + nowProvider: this.nowProvider, + }); + const queryService = this.queryService.setup({ uiSettings: core.uiSettings, storage: this.storage, + nowProvider: this.nowProvider, }); uiActions.registerTrigger(applyFilterTrigger); @@ -120,12 +131,6 @@ export class DataPublicPlugin })) ); - const searchService = this.searchService.setup(core, { - bfetch, - usageCollection, - expressions, - }); - inspector.registerView( getTableViewDescription(() => ({ uiActions: startServices().plugins.uiActions, @@ -195,6 +200,7 @@ export class DataPublicPlugin indexPatterns, query, search, + nowProvider: this.nowProvider, }; const SearchBar = createSearchBar({ diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 27a40b4e5ffcb..50b6b2223bd0a 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -580,6 +580,10 @@ export interface DataPublicPluginStart { autocomplete: AutocompleteStart; fieldFormats: FieldFormatsStart; indexPatterns: IndexPatternsContract; + // Warning: (ae-forgotten-export) The symbol "NowProviderPublicContract" needs to be exported by the entry point index.d.ts + // + // (undocumented) + nowProvider: NowProviderPublicContract; query: QueryStart; search: ISearchStart; ui: DataPublicPluginStartUi; @@ -2620,7 +2624,7 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:433:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:436:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:45:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/search/session/session_service.ts:50:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/search/session/session_service.ts:52:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/data/public/query/query_service.ts b/src/plugins/data/public/query/query_service.ts index fe7fdcbb1d113..e5f681549b06e 100644 --- a/src/plugins/data/public/query/query_service.ts +++ b/src/plugins/data/public/query/query_service.ts @@ -28,6 +28,7 @@ import { createQueryStateObservable } from './state_sync/create_global_query_obs import { QueryStringManager, QueryStringContract } from './query_string'; import { buildEsQuery, getEsQueryConfig } from '../../common'; import { getUiSettings } from '../services'; +import { NowProviderInternalContract } from '../now_provider'; import { IndexPattern } from '..'; /** @@ -38,6 +39,7 @@ import { IndexPattern } from '..'; interface QueryServiceSetupDependencies { storage: IStorageWrapper; uiSettings: IUiSettingsClient; + nowProvider: NowProviderInternalContract; } interface QueryServiceStartDependencies { @@ -53,10 +55,10 @@ export class QueryService { state$!: ReturnType; - public setup({ storage, uiSettings }: QueryServiceSetupDependencies) { + public setup({ storage, uiSettings, nowProvider }: QueryServiceSetupDependencies) { this.filterManager = new FilterManager(uiSettings); - const timefilterService = new TimefilterService(); + const timefilterService = new TimefilterService(nowProvider); this.timefilter = timefilterService.setup({ uiSettings, storage, diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts index c970dd521c142..3ad1f3daa992b 100644 --- a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts +++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts @@ -28,6 +28,7 @@ import { StubBrowserStorage } from '@kbn/test/jest'; import { connectToQueryState } from './connect_to_query_state'; import { TimefilterContract } from '../timefilter'; import { QueryState } from './types'; +import { createNowProviderMock } from '../../now_provider/mocks'; const connectToQueryGlobalState = (query: QueryStart, state: BaseStateContainer) => connectToQueryState(query, state, { @@ -79,6 +80,7 @@ describe('connect_to_global_state', () => { queryService.setup({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), + nowProvider: createNowProviderMock(), }); queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, @@ -312,6 +314,7 @@ describe('connect_to_app_state', () => { queryService.setup({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), + nowProvider: createNowProviderMock(), }); queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, @@ -490,6 +493,7 @@ describe('filters with different state', () => { queryService.setup({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), + nowProvider: createNowProviderMock(), }); queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, diff --git a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts index 47af09bfc7c0e..129a145ee0693 100644 --- a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts +++ b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts @@ -33,6 +33,7 @@ import { StubBrowserStorage } from '@kbn/test/jest'; import { TimefilterContract } from '../timefilter'; import { syncQueryStateWithUrl } from './sync_state_with_url'; import { QueryState } from './types'; +import { createNowProviderMock } from '../../now_provider/mocks'; const setupMock = coreMock.createSetup(); const startMock = coreMock.createStart(); @@ -73,6 +74,7 @@ describe('sync_query_state_with_url', () => { queryService.setup({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), + nowProvider: createNowProviderMock(), }); queryServiceStart = queryService.start({ uiSettings: startMock.uiSettings, diff --git a/src/plugins/data/public/query/timefilter/timefilter.test.ts b/src/plugins/data/public/query/timefilter/timefilter.test.ts index 6c1a4eff786f6..d8dfed002ea80 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.test.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.test.ts @@ -19,21 +19,12 @@ jest.useFakeTimers(); -jest.mock('./lib/parse_querystring', () => ({ - parseQueryString: () => { - return { - // Can not access local variable from within a mock - // @ts-ignore - forceNow: global.nowTime, - }; - }, -})); - import sinon from 'sinon'; import moment from 'moment'; import { Timefilter } from './timefilter'; import { Subscription } from 'rxjs'; import { TimeRange, RefreshInterval } from '../../../common'; +import { createNowProviderMock } from '../../now_provider/mocks'; import { timefilterServiceMock } from './timefilter_service.mock'; const timefilterSetupMock = timefilterServiceMock.createSetupContract(); @@ -42,16 +33,16 @@ const timefilterConfig = { timeDefaults: { from: 'now-15m', to: 'now' }, refreshIntervalDefaults: { pause: false, value: 0 }, }; -const timefilter = new Timefilter(timefilterConfig, timefilterSetupMock.history); + +const nowProviderMock = createNowProviderMock(); +const timefilter = new Timefilter(timefilterConfig, timefilterSetupMock.history, nowProviderMock); function stubNowTime(nowTime: any) { - // @ts-ignore - global.nowTime = nowTime; + nowProviderMock.get.mockImplementation(() => (nowTime ? new Date(nowTime) : new Date())); } function clearNowTimeStub() { - // @ts-ignore - delete global.nowTime; + nowProviderMock.get.mockReset(); } test('isTimeTouched is initially set to false', () => { diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 7278ceaaddcce..3ee2a3962e8ff 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -22,10 +22,11 @@ import { Subject, BehaviorSubject } from 'rxjs'; import moment from 'moment'; import { PublicMethodsOf } from '@kbn/utility-types'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; -import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; +import { NowProviderInternalContract } from '../../now_provider'; import { calculateBounds, + getAbsoluteTimeRange, getTime, IIndexPattern, RefreshInterval, @@ -60,7 +61,11 @@ export class Timefilter { private readonly timeDefaults: TimeRange; private readonly refreshIntervalDefaults: RefreshInterval; - constructor(config: TimefilterConfig, timeHistory: TimeHistoryContract) { + constructor( + config: TimefilterConfig, + timeHistory: TimeHistoryContract, + private readonly nowProvider: NowProviderInternalContract + ) { this._history = timeHistory; this.timeDefaults = config.timeDefaults; this.refreshIntervalDefaults = config.refreshIntervalDefaults; @@ -109,6 +114,13 @@ export class Timefilter { }; }; + /** + * Same as {@link getTime}, but also converts relative time range to absolute time range + */ + public getAbsoluteTime() { + return getAbsoluteTimeRange(this._time, { forceNow: this.nowProvider.get() }); + } + /** * Updates timefilter time. * Emits 'timeUpdate' and 'fetch' events when time changes @@ -177,7 +189,7 @@ export class Timefilter { public createFilter = (indexPattern: IIndexPattern, timeRange?: TimeRange) => { return getTime(indexPattern, timeRange ? timeRange : this._time, { - forceNow: this.getForceNow(), + forceNow: this.nowProvider.get(), }); }; @@ -186,7 +198,7 @@ export class Timefilter { } public calculateBounds(timeRange: TimeRange): TimeRangeBounds { - return calculateBounds(timeRange, { forceNow: this.getForceNow() }); + return calculateBounds(timeRange, { forceNow: this.nowProvider.get() }); } public getActiveBounds(): TimeRangeBounds | undefined { @@ -234,10 +246,6 @@ export class Timefilter { public getRefreshIntervalDefaults(): RefreshInterval { return _.cloneDeep(this.refreshIntervalDefaults); } - - private getForceNow = () => { - return getForceNow(); - }; } export type TimefilterContract = PublicMethodsOf; diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 9f1c64a1739a5..72ff49b9178fc 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -46,6 +46,7 @@ const createSetupContractMock = () => { createFilter: jest.fn(), getRefreshIntervalDefaults: jest.fn(), getTimeDefaults: jest.fn(), + getAbsoluteTime: jest.fn(), }; const historyMock: jest.Mocked = { diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.ts b/src/plugins/data/public/query/timefilter/timefilter_service.ts index 35b46de5f21b2..1f0c0345a0eae 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.ts @@ -21,6 +21,7 @@ import { IUiSettingsClient } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { TimeHistory, Timefilter, TimeHistoryContract, TimefilterContract } from './index'; import { UI_SETTINGS } from '../../../common'; +import { NowProviderInternalContract } from '../../now_provider'; /** * Filter Service @@ -33,13 +34,15 @@ export interface TimeFilterServiceDependencies { } export class TimefilterService { + constructor(private readonly nowProvider: NowProviderInternalContract) {} + public setup({ uiSettings, storage }: TimeFilterServiceDependencies): TimefilterSetup { const timefilterConfig = { timeDefaults: uiSettings.get(UI_SETTINGS.TIMEPICKER_TIME_DEFAULTS), refreshIntervalDefaults: uiSettings.get(UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS), }; const history = new TimeHistory(storage); - const timefilter = new Timefilter(timefilterConfig, history); + const timefilter = new Timefilter(timefilterConfig, history, this.nowProvider); return { timefilter, diff --git a/src/plugins/data/public/search/aggs/aggs_service.test.ts b/src/plugins/data/public/search/aggs/aggs_service.test.ts index bc4992384b0c2..86a466b699710 100644 --- a/src/plugins/data/public/search/aggs/aggs_service.test.ts +++ b/src/plugins/data/public/search/aggs/aggs_service.test.ts @@ -31,6 +31,7 @@ import { AggsStartDependencies, createGetConfig, } from './aggs_service'; +import { createNowProviderMock } from '../../now_provider/mocks'; const { uiSettings } = coreMock.createSetup(); @@ -44,6 +45,7 @@ describe('AggsService - public', () => { setupDeps = { registerFunction: expressionsPluginMock.createSetupContract().registerFunction, uiSettings, + nowProvider: createNowProviderMock(), }; startDeps = { fieldFormats: fieldFormatsServiceMock.createStartContract(), diff --git a/src/plugins/data/public/search/aggs/aggs_service.ts b/src/plugins/data/public/search/aggs/aggs_service.ts index 7b5edac0280d9..59032a8608632 100644 --- a/src/plugins/data/public/search/aggs/aggs_service.ts +++ b/src/plugins/data/public/search/aggs/aggs_service.ts @@ -22,7 +22,6 @@ import { Subscription } from 'rxjs'; import { IUiSettingsClient } from 'src/core/public'; import { ExpressionsServiceSetup } from 'src/plugins/expressions/common'; import { FieldFormatsStart } from '../../field_formats'; -import { getForceNow } from '../../query/timefilter/lib/get_force_now'; import { calculateBounds, TimeRange } from '../../../common'; import { aggsRequiredUiSettings, @@ -33,6 +32,7 @@ import { } from '../../../common/search/aggs'; import { AggsSetup, AggsStart } from './types'; import { IndexPatternsContract } from '../../index_patterns'; +import { NowProviderInternalContract } from '../../now_provider'; /** * Aggs needs synchronous access to specific uiSettings. Since settings can change @@ -63,6 +63,7 @@ export function createGetConfig( export interface AggsSetupDependencies { registerFunction: ExpressionsServiceSetup['registerFunction']; uiSettings: IUiSettingsClient; + nowProvider: NowProviderInternalContract; } /** @internal */ @@ -82,15 +83,17 @@ export class AggsService { private readonly initializedAggTypes = new Map(); private getConfig?: AggsCommonStartDependencies['getConfig']; private subscriptions: Subscription[] = []; + private nowProvider!: NowProviderInternalContract; /** - * getForceNow uses window.location, so we must have a separate implementation + * NowGetter uses window.location, so we must have a separate implementation * of calculateBounds on the client and the server. */ private calculateBounds = (timeRange: TimeRange) => - calculateBounds(timeRange, { forceNow: getForceNow() }); + calculateBounds(timeRange, { forceNow: this.nowProvider.get() }); - public setup({ registerFunction, uiSettings }: AggsSetupDependencies): AggsSetup { + public setup({ registerFunction, uiSettings, nowProvider }: AggsSetupDependencies): AggsSetup { + this.nowProvider = nowProvider; this.getConfig = createGetConfig(uiSettings, aggsRequiredUiSettings, this.subscriptions); return this.aggsCommonService.setup({ registerFunction }); diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index d8d90ea464a73..63138ee1b0454 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -53,6 +53,7 @@ export function getFunctionDefinition({ deserializeFieldFormat, indexPatterns, searchSource, + getNow, } = await getStartDependencies(); const indexPattern = await indexPatterns.create(args.index.value, true); @@ -75,6 +76,7 @@ export function getFunctionDefinition({ searchSourceService: searchSource, timeFields: args.timeFields, timeRange: get(input, 'timeRange', undefined), + getNow, }); }, }); @@ -102,12 +104,13 @@ export function getEsaggs({ return getFunctionDefinition({ getStartDependencies: async () => { const [, , self] = await getStartServices(); - const { fieldFormats, indexPatterns, search } = self; + const { fieldFormats, indexPatterns, search, nowProvider } = self; return { aggs: search.aggs, deserializeFieldFormat: fieldFormats.deserialize.bind(fieldFormats), indexPatterns, searchSource: search.searchSource, + getNow: () => nowProvider.get(), }; }, }); diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 947dac1b32640..0656d3ac3aa03 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -115,12 +115,14 @@ describe('SearchInterceptor', () => { }: { isRestore?: boolean; isStored?: boolean; - sessionId?: string; + sessionId: string; }) => { const sessionServiceMock = searchMock.session as jest.Mocked; - sessionServiceMock.getSessionId.mockImplementation(() => sessionId); - sessionServiceMock.isRestore.mockImplementation(() => isRestore); - sessionServiceMock.isStored.mockImplementation(() => isStored); + sessionServiceMock.getSearchOptions.mockImplementation(() => ({ + sessionId, + isRestore, + isStored, + })); fetchMock.mockResolvedValue({ result: 200 }); }; @@ -130,30 +132,14 @@ describe('SearchInterceptor', () => { afterEach(() => { const sessionServiceMock = searchMock.session as jest.Mocked; - sessionServiceMock.getSessionId.mockReset(); - sessionServiceMock.isRestore.mockReset(); - sessionServiceMock.isStored.mockReset(); + sessionServiceMock.getSearchOptions.mockReset(); fetchMock.mockReset(); }); - test('infers isRestore from session service state', async () => { + test('gets session search options from session service', async () => { const sessionId = 'sid'; setup({ isRestore: true, - sessionId, - }); - - await searchInterceptor.search(mockRequest, { sessionId }).toPromise(); - expect(fetchMock.mock.calls[0][0]).toEqual( - expect.objectContaining({ - options: { sessionId: 'sid', isStored: false, isRestore: true }, - }) - ); - }); - - test('infers isStored from session service state', async () => { - const sessionId = 'sid'; - setup({ isStored: true, sessionId, }); @@ -161,41 +147,13 @@ describe('SearchInterceptor', () => { await searchInterceptor.search(mockRequest, { sessionId }).toPromise(); expect(fetchMock.mock.calls[0][0]).toEqual( expect.objectContaining({ - options: { sessionId: 'sid', isStored: true, isRestore: false }, - }) - ); - }); - - test('skips isRestore & isStore in case not a current session Id', async () => { - setup({ - isStored: true, - isRestore: true, - sessionId: 'session id', - }); - - await searchInterceptor - .search(mockRequest, { sessionId: 'different session id' }) - .toPromise(); - expect(fetchMock.mock.calls[0][0]).toEqual( - expect.objectContaining({ - options: { sessionId: 'different session id', isStored: false, isRestore: false }, + options: { sessionId, isStored: true, isRestore: true }, }) ); - }); - test('skips isRestore & isStore in case no session Id', async () => { - setup({ - isStored: true, - isRestore: true, - sessionId: undefined, - }); - - await searchInterceptor.search(mockRequest, { sessionId: 'sessionId' }).toPromise(); - expect(fetchMock.mock.calls[0][0]).toEqual( - expect.objectContaining({ - options: { sessionId: 'sessionId', isStored: false, isRestore: false }, - }) - ); + expect( + (searchMock.session as jest.Mocked).getSearchOptions + ).toHaveBeenCalledWith(sessionId); }); }); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 8548a2a9f2b2a..b81a6c4450cc4 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -130,16 +130,12 @@ export class SearchInterceptor { ): Promise { const { abortSignal, ...requestOptions } = options || {}; - const isCurrentSession = - options?.sessionId && this.deps.session.getSessionId() === options.sessionId; - return this.batchedFetch( { request, options: { ...requestOptions, - isStored: isCurrentSession ? this.deps.session.isStored() : false, - isRestore: isCurrentSession ? this.deps.session.isRestore() : false, + ...(options?.sessionId && this.deps.session.getSearchOptions(options.sessionId)), }, }, abortSignal diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 1c49de8f0ff4b..eef6190fe78c5 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -53,12 +53,14 @@ import { } from '../../common/search/aggs/buckets/shard_delay'; import { aggShardDelay } from '../../common/search/aggs/buckets/shard_delay_fn'; import { DataPublicPluginStart, DataStartDependencies } from '../types'; +import { NowProviderInternalContract } from '../now_provider'; /** @internal */ export interface SearchServiceSetupDependencies { bfetch: BfetchPublicSetup; expressions: ExpressionsSetup; usageCollection?: UsageCollectionSetup; + nowProvider: NowProviderInternalContract; } /** @internal */ @@ -79,7 +81,7 @@ export class SearchService implements Plugin { public setup( { http, getStartServices, notifications, uiSettings }: CoreSetup, - { bfetch, expressions, usageCollection }: SearchServiceSetupDependencies + { bfetch, expressions, usageCollection, nowProvider }: SearchServiceSetupDependencies ): ISearchSetup { this.usageCollector = createUsageCollector(getStartServices, usageCollection); @@ -87,7 +89,8 @@ export class SearchService implements Plugin { this.sessionService = new SessionService( this.initializerContext, getStartServices, - this.sessionsClient + this.sessionsClient, + nowProvider ); /** * A global object that intercepts all searches and provides convenience methods for cancelling @@ -118,6 +121,7 @@ export class SearchService implements Plugin { const aggs = this.aggsService.setup({ registerFunction: expressions.registerFunction, uiSettings, + nowProvider, }); if (this.initializerContext.config.get().search.aggs.shardDelay.enabled) { diff --git a/src/plugins/data/public/search/session/mocks.ts b/src/plugins/data/public/search/session/mocks.ts index ea0cd8be03f27..13dd054c122d5 100644 --- a/src/plugins/data/public/search/session/mocks.ts +++ b/src/plugins/data/public/search/session/mocks.ts @@ -49,5 +49,7 @@ export function getSessionServiceMock(): jest.Mocked { isStored: jest.fn(), isRestore: jest.fn(), save: jest.fn(), + isCurrentSession: jest.fn(), + getSearchOptions: jest.fn(), }; } diff --git a/src/plugins/data/public/search/session/search_session_state.test.ts b/src/plugins/data/public/search/session/search_session_state.test.ts index 539fc8252b2a5..c2cb75b9a7493 100644 --- a/src/plugins/data/public/search/session/search_session_state.test.ts +++ b/src/plugins/data/public/search/session/search_session_state.test.ts @@ -31,6 +31,7 @@ describe('Session state container', () => { state.transitions.start(); expect(state.selectors.getState()).toBe(SearchSessionState.None); expect(state.get().sessionId).not.toBeUndefined(); + expect(state.get().startTime).not.toBeUndefined(); }); test('track', () => { @@ -56,6 +57,7 @@ describe('Session state container', () => { state.transitions.clear(); expect(state.selectors.getState()).toBe(SearchSessionState.None); expect(state.get().sessionId).toBeUndefined(); + expect(state.get().startTime).toBeUndefined(); }); test('cancel', () => { diff --git a/src/plugins/data/public/search/session/search_session_state.ts b/src/plugins/data/public/search/session/search_session_state.ts index 7a35a65a600d7..0894de13d53a9 100644 --- a/src/plugins/data/public/search/session/search_session_state.ts +++ b/src/plugins/data/public/search/session/search_session_state.ts @@ -105,6 +105,11 @@ export interface SessionStateInternal { * If user has explicitly canceled search requests */ isCanceled: boolean; + + /** + * Start time of current session + */ + startTime?: Date; } const createSessionDefaultState: < @@ -132,7 +137,11 @@ export interface SessionPureTransitions< } export const sessionPureTransitions: SessionPureTransitions = { - start: (state) => () => ({ ...createSessionDefaultState(), sessionId: uuid.v4() }), + start: (state) => () => ({ + ...createSessionDefaultState(), + sessionId: uuid.v4(), + startTime: new Date(), + }), restore: (state) => (sessionId: string) => ({ ...createSessionDefaultState(), sessionId, @@ -216,6 +225,7 @@ export const createSessionStateContainer = ( ): { stateContainer: SessionStateContainer; sessionState$: Observable; + sessionStartTime$: Observable; } => { const stateContainer = createStateContainer( createSessionDefaultState(), @@ -229,8 +239,16 @@ export const createSessionStateContainer = ( distinctUntilChanged(), shareReplay(1) ); + + const sessionStartTime$: Observable = stateContainer.state$.pipe( + map(() => stateContainer.get().startTime), + distinctUntilChanged(), + shareReplay(1) + ); + return { stateContainer, sessionState$, + sessionStartTime$, }; }; diff --git a/src/plugins/data/public/search/session/session_service.test.ts b/src/plugins/data/public/search/session/session_service.test.ts index cf083239b1571..8fbc034b3a4c8 100644 --- a/src/plugins/data/public/search/session/session_service.test.ts +++ b/src/plugins/data/public/search/session/session_service.test.ts @@ -23,17 +23,30 @@ import { take, toArray } from 'rxjs/operators'; import { getSessionsClientMock } from './mocks'; import { BehaviorSubject } from 'rxjs'; import { SearchSessionState } from './search_session_state'; +import { createNowProviderMock } from '../../now_provider/mocks'; +import { NowProviderInternalContract } from '../../now_provider'; describe('Session service', () => { let sessionService: ISessionService; let state$: BehaviorSubject; + let nowProvider: jest.Mocked; beforeEach(() => { const initializerContext = coreMock.createPluginInitializerContext(); + const startService = coreMock.createSetup().getStartServices; + nowProvider = createNowProviderMock(); sessionService = new SessionService( initializerContext, - coreMock.createSetup().getStartServices, + () => + startService().then(([coreStart, ...rest]) => [ + { + ...coreStart, + application: { ...coreStart.application, currentAppId$: new BehaviorSubject('app') }, + }, + ...rest, + ]), getSessionsClientMock(), + nowProvider, { freezeState: false } // needed to use mocks inside state container ); state$ = new BehaviorSubject(SearchSessionState.None); @@ -44,8 +57,10 @@ describe('Session service', () => { it('Creates and clears a session', async () => { sessionService.start(); expect(sessionService.getSessionId()).not.toBeUndefined(); + expect(nowProvider.set).toHaveBeenCalled(); sessionService.clear(); expect(sessionService.getSessionId()).toBeUndefined(); + expect(nowProvider.reset).toHaveBeenCalled(); }); it('Restores a session', async () => { @@ -93,4 +108,63 @@ describe('Session service', () => { expect(abort).toBeCalledTimes(3); }); }); + + test('getSearchOptions infers isRestore & isStored from state', async () => { + const sessionId = sessionService.start(); + const someOtherId = 'some-other-id'; + + expect(sessionService.getSearchOptions(someOtherId)).toEqual({ + isStored: false, + isRestore: false, + sessionId: someOtherId, + }); + expect(sessionService.getSearchOptions(sessionId)).toEqual({ + isStored: false, + isRestore: false, + sessionId, + }); + + sessionService.setSearchSessionInfoProvider({ + getName: async () => 'Name', + getUrlGeneratorData: async () => ({ + urlGeneratorId: 'id', + initialState: {}, + restoreState: {}, + }), + }); + await sessionService.save(); + + expect(sessionService.getSearchOptions(someOtherId)).toEqual({ + isStored: false, + isRestore: false, + sessionId: someOtherId, + }); + expect(sessionService.getSearchOptions(sessionId)).toEqual({ + isStored: true, + isRestore: false, + sessionId, + }); + + await sessionService.restore(sessionId); + + expect(sessionService.getSearchOptions(someOtherId)).toEqual({ + isStored: false, + isRestore: false, + sessionId: someOtherId, + }); + expect(sessionService.getSearchOptions(sessionId)).toEqual({ + isStored: true, + isRestore: true, + sessionId, + }); + }); + test('isCurrentSession', () => { + expect(sessionService.isCurrentSession()).toBeFalsy(); + + const sessionId = sessionService.start(); + + expect(sessionService.isCurrentSession()).toBeFalsy(); + expect(sessionService.isCurrentSession('some-other')).toBeFalsy(); + expect(sessionService.isCurrentSession(sessionId)).toBeTruthy(); + }); }); diff --git a/src/plugins/data/public/search/session/session_service.ts b/src/plugins/data/public/search/session/session_service.ts index 2bbb762fcfe9f..26fa5bd10c485 100644 --- a/src/plugins/data/public/search/session/session_service.ts +++ b/src/plugins/data/public/search/session/session_service.ts @@ -29,6 +29,8 @@ import { SessionStateContainer, } from './search_session_state'; import { ISessionsClient } from './sessions_client'; +import { ISearchOptions } from '../../../common'; +import { NowProviderInternalContract } from '../../now_provider'; export type ISessionService = PublicContract; @@ -60,40 +62,54 @@ export class SessionService { private readonly state: SessionStateContainer; private searchSessionInfoProvider?: SearchSessionInfoProvider; - private appChangeSubscription$?: Subscription; + private subscription = new Subscription(); private curApp?: string; constructor( initializerContext: PluginInitializerContext, getStartServices: StartServicesAccessor, private readonly sessionsClient: ISessionsClient, + private readonly nowProvider: NowProviderInternalContract, { freezeState = true }: { freezeState: boolean } = { freezeState: true } ) { - const { stateContainer, sessionState$ } = createSessionStateContainer({ + const { + stateContainer, + sessionState$, + sessionStartTime$, + } = createSessionStateContainer({ freeze: freezeState, }); this.state$ = sessionState$; this.state = stateContainer; + this.subscription.add( + sessionStartTime$.subscribe((startTime) => { + if (startTime) this.nowProvider.set(startTime); + else this.nowProvider.reset(); + }) + ); + getStartServices().then(([coreStart]) => { // Apps required to clean up their sessions before unmounting // Make sure that apps don't leave sessions open. - this.appChangeSubscription$ = coreStart.application.currentAppId$.subscribe((appName) => { - if (this.state.get().sessionId) { - const message = `Application '${this.curApp}' had an open session while navigating`; - if (initializerContext.env.mode.dev) { - // TODO: This setTimeout is necessary due to a race condition while navigating. - setTimeout(() => { - coreStart.fatalErrors.add(message); - }, 100); - } else { - // eslint-disable-next-line no-console - console.warn(message); - this.clear(); + this.subscription.add( + coreStart.application.currentAppId$.subscribe((appName) => { + if (this.state.get().sessionId) { + const message = `Application '${this.curApp}' had an open session while navigating`; + if (initializerContext.env.mode.dev) { + // TODO: This setTimeout is necessary due to a race condition while navigating. + setTimeout(() => { + coreStart.fatalErrors.add(message); + }, 100); + } else { + // eslint-disable-next-line no-console + console.warn(message); + this.clear(); + } } - } - this.curApp = appName; - }); + this.curApp = appName; + }) + ); }); } @@ -122,9 +138,7 @@ export class SessionService { } public destroy() { - if (this.appChangeSubscription$) { - this.appChangeSubscription$.unsubscribe(); - } + this.subscription.unsubscribe(); this.clear(); } @@ -243,4 +257,27 @@ export class SessionService { this.state.transitions.store(); } } + + /** + * Checks if passed sessionId is a current sessionId + * @param sessionId + */ + public isCurrentSession(sessionId?: string): boolean { + return !!sessionId && this.getSessionId() === sessionId; + } + + /** + * Infers search session options for sessionId using current session state + * @param sessionId + */ + public getSearchOptions( + sessionId: string + ): Required> { + const isCurrentSession = this.isCurrentSession(sessionId); + return { + sessionId, + isRestore: isCurrentSession ? this.isRestore() : false, + isStored: isCurrentSession ? this.isStored() : false, + }; + } } diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index c7b66acfc6c7a..e38cabe313b6c 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -32,6 +32,7 @@ import { IndexPatternsContract } from './index_patterns'; import { IndexPatternSelectProps, StatefulSearchBarProps } from './ui'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { Setup as InspectorSetup } from '../../inspector/public'; +import { NowProviderPublicContract } from './now_provider'; export interface DataPublicPluginEnhancements { search: SearchEnhancements; @@ -118,6 +119,8 @@ export interface DataPublicPluginStart { * {@link DataPublicPluginStartUi} */ ui: DataPublicPluginStartUi; + + nowProvider: NowProviderPublicContract; } export interface IDataPluginServices extends Partial { diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 4c5cb864b5111..839add1aeb22d 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -295,7 +295,7 @@ function discoverController($element, $route, $scope, $timeout, Promise, uiCapab createSearchSessionRestorationDataProvider({ appStateContainer, data, - getSavedSearchId: () => savedSearch.id, + getSavedSearch: () => savedSearch, }) ); diff --git a/src/plugins/discover/public/application/angular/discover_state.test.ts b/src/plugins/discover/public/application/angular/discover_state.test.ts index 2914ce8f17a09..e05a3028c5ca9 100644 --- a/src/plugins/discover/public/application/angular/discover_state.test.ts +++ b/src/plugins/discover/public/application/angular/discover_state.test.ts @@ -17,8 +17,14 @@ * under the License. */ -import { getState, GetStateReturn } from './discover_state'; +import { + getState, + GetStateReturn, + createSearchSessionRestorationDataProvider, +} from './discover_state'; import { createBrowserHistory, History } from 'history'; +import { dataPluginMock } from '../../../../data/public/mocks'; +import { SavedSearch } from '../../saved_searches'; let history: History; let state: GetStateReturn; @@ -103,3 +109,30 @@ describe('Test discover state with legacy migration', () => { `); }); }); + +describe('createSearchSessionRestorationDataProvider', () => { + let mockSavedSearch: SavedSearch = ({} as unknown) as SavedSearch; + const searchSessionInfoProvider = createSearchSessionRestorationDataProvider({ + data: dataPluginMock.createStartContract(), + appStateContainer: getState({ + history: createBrowserHistory(), + }).appStateContainer, + getSavedSearch: () => mockSavedSearch, + }); + + describe('session name', () => { + test('No saved search returns default name', async () => { + expect(await searchSessionInfoProvider.getName()).toBe('Discover'); + }); + + test('Saved Search with a title returns saved search title', async () => { + mockSavedSearch = ({ id: 'id', title: 'Name' } as unknown) as SavedSearch; + expect(await searchSessionInfoProvider.getName()).toBe('Name'); + }); + + test('Saved Search without a title returns default name', async () => { + mockSavedSearch = ({ id: 'id', title: undefined } as unknown) as SavedSearch; + expect(await searchSessionInfoProvider.getName()).toBe('Discover'); + }); + }); +}); diff --git a/src/plugins/discover/public/application/angular/discover_state.ts b/src/plugins/discover/public/application/angular/discover_state.ts index f52bc8b49ba42..69291872fa855 100644 --- a/src/plugins/discover/public/application/angular/discover_state.ts +++ b/src/plugins/discover/public/application/angular/discover_state.ts @@ -17,6 +17,7 @@ * under the License. */ import { isEqual } from 'lodash'; +import { i18n } from '@kbn/i18n'; import { History } from 'history'; import { NotificationsStart } from 'kibana/public'; import { @@ -38,6 +39,7 @@ import { import { migrateLegacyQuery } from '../helpers/migrate_legacy_query'; import { DiscoverGridSettings } from '../components/discover_grid/types'; import { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from '../../url_generator'; +import { SavedSearch } from '../../saved_searches'; export interface AppState { /** @@ -264,15 +266,32 @@ export function isEqualState(stateA: AppState, stateB: AppState) { export function createSearchSessionRestorationDataProvider(deps: { appStateContainer: StateContainer; data: DataPublicPluginStart; - getSavedSearchId: () => string | undefined; + getSavedSearch: () => SavedSearch; }): SearchSessionInfoProvider { + const getSavedSearchId = () => deps.getSavedSearch().id; return { - getName: async () => 'Discover', + getName: async () => { + const savedSearch = deps.getSavedSearch(); + return ( + (savedSearch.id && savedSearch.title) || + i18n.translate('discover.discoverDefaultSearchSessionName', { + defaultMessage: 'Discover', + }) + ); + }, getUrlGeneratorData: async () => { return { urlGeneratorId: DISCOVER_APP_URL_GENERATOR, - initialState: createUrlGeneratorState({ ...deps, forceAbsoluteTime: false }), - restoreState: createUrlGeneratorState({ ...deps, forceAbsoluteTime: true }), + initialState: createUrlGeneratorState({ + ...deps, + getSavedSearchId, + forceAbsoluteTime: false, + }), + restoreState: createUrlGeneratorState({ + ...deps, + getSavedSearchId, + forceAbsoluteTime: true, + }), }; }, }; @@ -282,11 +301,14 @@ function createUrlGeneratorState({ appStateContainer, data, getSavedSearchId, - forceAbsoluteTime, // TODO: not implemented + forceAbsoluteTime, }: { appStateContainer: StateContainer; data: DataPublicPluginStart; getSavedSearchId: () => string | undefined; + /** + * Can force time range from time filter to convert from relative to absolute time range + */ forceAbsoluteTime: boolean; }): DiscoverUrlGeneratorState { const appState = appStateContainer.get(); @@ -295,7 +317,9 @@ function createUrlGeneratorState({ indexPatternId: appState.index, query: appState.query, savedSearchId: getSavedSearchId(), - timeRange: data.query.timefilter.timefilter.getTime(), // TODO: handle relative time range + timeRange: forceAbsoluteTime + ? data.query.timefilter.timefilter.getAbsoluteTime() + : data.query.timefilter.timefilter.getTime(), searchSessionId: data.search.session.getSessionId(), columns: appState.columns, sort: appState.sort, diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable.ts b/src/plugins/discover/public/application/embeddable/search_embeddable.ts index e4a8ab7bc67ff..6919dc1bef286 100644 --- a/src/plugins/discover/public/application/embeddable/search_embeddable.ts +++ b/src/plugins/discover/public/application/embeddable/search_embeddable.ts @@ -29,7 +29,6 @@ import { Filter, TimeRange, FilterManager, - getTime, Query, IFieldType, } from '../../../../data/public'; @@ -98,7 +97,6 @@ export class SearchEmbeddable private panelTitle: string = ''; private filtersSearchSource?: ISearchSource; private searchInstance?: JQLite; - private autoRefreshFetchSubscription?: Subscription; private subscription?: Subscription; public readonly type = SEARCH_EMBEDDABLE_TYPE; private filterManager: FilterManager; @@ -148,10 +146,6 @@ export class SearchEmbeddable }; this.initializeSearchScope(); - this.autoRefreshFetchSubscription = this.services.timefilter - .getAutoRefreshFetch$() - .subscribe(this.fetch); - this.subscription = this.getUpdated$().subscribe(() => { this.panelTitle = this.output.title || ''; @@ -199,9 +193,7 @@ export class SearchEmbeddable if (this.subscription) { this.subscription.unsubscribe(); } - if (this.autoRefreshFetchSubscription) { - this.autoRefreshFetchSubscription.unsubscribe(); - } + if (this.abortController) this.abortController.abort(); } @@ -224,7 +216,7 @@ export class SearchEmbeddable const timeRangeSearchSource = searchSource.create(); timeRangeSearchSource.setField('filter', () => { if (!this.searchScope || !this.input.timeRange) return; - return getTime(indexPattern, this.input.timeRange); + return this.services.timefilter.createFilter(indexPattern, this.input.timeRange); }); this.filtersSearchSource = searchSource.create(); diff --git a/src/plugins/discover/public/url_generator.test.ts b/src/plugins/discover/public/url_generator.test.ts index 95bff6b1fdc9c..f87ef4f91108a 100644 --- a/src/plugins/discover/public/url_generator.test.ts +++ b/src/plugins/discover/public/url_generator.test.ts @@ -62,7 +62,7 @@ describe('Discover url generator', () => { const url = await generator.createUrl({ savedSearchId }); const { _a, _g } = getStatesFromKbnUrl(url, ['_a', '_g']); - expect(url.startsWith(`${appBasePath}#/${savedSearchId}`)).toBe(true); + expect(url.startsWith(`${appBasePath}#/view/${savedSearchId}`)).toBe(true); expect(_a).toEqual({}); expect(_g).toEqual({}); }); diff --git a/src/plugins/discover/public/url_generator.ts b/src/plugins/discover/public/url_generator.ts index 6d86818910b11..d1b574c360d88 100644 --- a/src/plugins/discover/public/url_generator.ts +++ b/src/plugins/discover/public/url_generator.ts @@ -119,7 +119,7 @@ export class DiscoverUrlGenerator sort, interval, }: DiscoverUrlGeneratorState): Promise => { - const savedSearchPath = savedSearchId ? encodeURIComponent(savedSearchId) : ''; + const savedSearchPath = savedSearchId ? `view/${encodeURIComponent(savedSearchId)}` : ''; const appState: { query?: Query; filters?: Filter[]; diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json new file mode 100644 index 0000000000000..ec98199c3423e --- /dev/null +++ b/src/plugins/discover/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*", "../../../typings/**/*"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../embeddable/tsconfig.json" }, + { "path": "../inspector/tsconfig.json" }, + { "path": "../url_forwarding/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + { "path": "../navigation/tsconfig.json" }, + { "path": "../ui_actions/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../share/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json" } + ] +} diff --git a/src/plugins/embeddable/README.asciidoc b/src/plugins/embeddable/README.asciidoc index 5e3c5066f46c7..daa6040eab7eb 100644 --- a/src/plugins/embeddable/README.asciidoc +++ b/src/plugins/embeddable/README.asciidoc @@ -22,7 +22,7 @@ There is also an example of rendering dashboard container outside of dashboard a === Docs -(./docs/README.md)[Embeddable docs, guides & caveats] +link:./docs/README.md[Embeddable docs, guides & caveats] === API docs diff --git a/src/plugins/es_ui_shared/tsconfig.json b/src/plugins/es_ui_shared/tsconfig.json new file mode 100644 index 0000000000000..9bcda2e0614de --- /dev/null +++ b/src/plugins/es_ui_shared/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "__packages_do_not_import__/**/*", + "common/**/*", + "public/**/*", + "server/**/*", + "static/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + ] +} diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 609022f8a55c0..a1841d8fa3743 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -183,6 +183,7 @@ export class Execution< logDatatable: (name: string, datatable: Datatable) => { inspectorAdapters.tables[name] = datatable; }, + isSyncColorsEnabled: () => execution.params.syncColors, ...(execution.params as any).extraContext, }; } diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts index a1b25c3802f4b..bac9cda128697 100644 --- a/src/plugins/expressions/common/execution/types.ts +++ b/src/plugins/expressions/common/execution/types.ts @@ -83,6 +83,11 @@ export interface ExecutionContext< type: string, id: string ) => Promise>; + + /** + * Returns the state (true|false) of the sync colors across panels switch. + */ + isSyncColorsEnabled?: () => boolean; } /** diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index ec1fffe64f102..3adf452ef8bd3 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -70,6 +70,8 @@ export interface ExpressionExecutionParams { searchSessionId?: string; + syncColors?: boolean; + inspectorAdapters?: Adapters; } diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index 1cf499ce2635a..4db070f88a17f 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -154,6 +154,7 @@ export class ExpressionLoader { inspectorAdapters: params.inspectorAdapters, searchSessionId: params.searchSessionId, debug: params.debug, + syncColors: params.syncColors, }); const prevDataHandler = this.execution; @@ -189,6 +190,7 @@ export class ExpressionLoader { if (params.searchSessionId && this.params) { this.params.searchSessionId = params.searchSessionId; } + this.params.syncColors = params.syncColors; this.params.debug = Boolean(params.debug); this.params.inspectorAdapters = (params.inspectorAdapters || diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md index 5c018adc0131b..df24882f6eb58 100644 --- a/src/plugins/expressions/public/public.api.md +++ b/src/plugins/expressions/public/public.api.md @@ -143,6 +143,7 @@ export interface ExecutionContext ExecutionContextSearch; getSearchSessionId: () => string | undefined; inspectorAdapters: InspectorAdapters; + isSyncColorsEnabled?: () => boolean; types: Record; variables: Record; } diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md index 71199560ee0c7..0f5c3c8ae8736 100644 --- a/src/plugins/expressions/server/server.api.md +++ b/src/plugins/expressions/server/server.api.md @@ -141,6 +141,7 @@ export interface ExecutionContext ExecutionContextSearch; getSearchSessionId: () => string | undefined; inspectorAdapters: InspectorAdapters; + isSyncColorsEnabled?: () => boolean; types: Record; variables: Record; } diff --git a/src/plugins/input_control_vis/kibana.json b/src/plugins/input_control_vis/kibana.json index c6d1157f5ff25..5acb79a8ab038 100644 --- a/src/plugins/input_control_vis/kibana.json +++ b/src/plugins/input_control_vis/kibana.json @@ -4,6 +4,13 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "visualizations", "visDefaultEditor"], - "requiredBundles": ["kibanaReact"] + "requiredPlugins": [ + "data", + "expressions", + "visDefaultEditor", + "visualizations" + ], + "requiredBundles": [ + "kibanaReact" + ] } diff --git a/src/plugins/lens_oss/tsconfig.json b/src/plugins/lens_oss/tsconfig.json new file mode 100644 index 0000000000000..d7bbc593fa87b --- /dev/null +++ b/src/plugins/lens_oss/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" } + ] +} diff --git a/src/plugins/presentation_util/tsconfig.json b/src/plugins/presentation_util/tsconfig.json new file mode 100644 index 0000000000000..1e3756f45e953 --- /dev/null +++ b/src/plugins/presentation_util/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../dashboard/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + ] +} diff --git a/src/plugins/runtime_fields/README.mdx b/src/plugins/runtime_fields/README.mdx deleted file mode 100644 index 15985b07caf96..0000000000000 --- a/src/plugins/runtime_fields/README.mdx +++ /dev/null @@ -1,4 +0,0 @@ - -# Runtime Fields - -The runtime fields plugin provides types and constants for OSS and xpack runtime field related code. diff --git a/src/plugins/runtime_fields/kibana.json b/src/plugins/runtime_fields/kibana.json deleted file mode 100644 index e71116f81532e..0000000000000 --- a/src/plugins/runtime_fields/kibana.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "id": "runtimeFields", - "version": "kibana", - "server": false, - "ui": true -} diff --git a/src/plugins/saved_objects_management/tsconfig.json b/src/plugins/saved_objects_management/tsconfig.json new file mode 100644 index 0000000000000..eb047c346714c --- /dev/null +++ b/src/plugins/saved_objects_management/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../dashboard/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../discover/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../management/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + ] +} diff --git a/src/plugins/spaces_oss/README.md b/src/plugins/spaces_oss/README.md new file mode 100644 index 0000000000000..73de736d6fb4e --- /dev/null +++ b/src/plugins/spaces_oss/README.md @@ -0,0 +1,3 @@ +# SpacesOss + +Bridge plugin for consumption of the Spaces feature from OSS plugins. diff --git a/src/plugins/runtime_fields/common/index.ts b/src/plugins/spaces_oss/common/index.ts similarity index 93% rename from src/plugins/runtime_fields/common/index.ts rename to src/plugins/spaces_oss/common/index.ts index b08ac661a4bd6..8a04df861b5e5 100644 --- a/src/plugins/runtime_fields/common/index.ts +++ b/src/plugins/spaces_oss/common/index.ts @@ -17,5 +17,4 @@ * under the License. */ -export * from './constants'; -export * from './types'; +export { Space } from './types'; diff --git a/src/plugins/spaces_oss/common/types.ts b/src/plugins/spaces_oss/common/types.ts new file mode 100644 index 0000000000000..6eff95a8d3d9f --- /dev/null +++ b/src/plugins/spaces_oss/common/types.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface Space { + id: string; + name: string; + description?: string; + color?: string; + initials?: string; + disabledFeatures: string[]; + _reserved?: boolean; + imageUrl?: string; +} diff --git a/src/plugins/vis_type_timeseries/common/field_types.js b/src/plugins/spaces_oss/jest.config.js similarity index 86% rename from src/plugins/vis_type_timeseries/common/field_types.js rename to src/plugins/spaces_oss/jest.config.js index f5323f1542a31..d60652d15bfad 100644 --- a/src/plugins/vis_type_timeseries/common/field_types.js +++ b/src/plugins/spaces_oss/jest.config.js @@ -17,10 +17,8 @@ * under the License. */ -export const FIELD_TYPES = { - BOOLEAN: 'boolean', - DATE: 'date', - GEO: 'geo_point', - NUMBER: 'number', - STRING: 'string', +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/spaces_oss'], }; diff --git a/src/plugins/spaces_oss/kibana.json b/src/plugins/spaces_oss/kibana.json new file mode 100644 index 0000000000000..e048fb7ffb79c --- /dev/null +++ b/src/plugins/spaces_oss/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "spacesOss", + "version": "kibana", + "server": false, + "ui": true, + "requiredPlugins": [], + "optionalPlugins": [] +} diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.js b/src/plugins/spaces_oss/public/api.mock.ts similarity index 77% rename from src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.js rename to src/plugins/spaces_oss/public/api.mock.ts index ff6c2cc0767f5..21d991c33e382 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.js +++ b/src/plugins/spaces_oss/public/api.mock.ts @@ -17,12 +17,14 @@ * under the License. */ -import _ from 'lodash'; +import { of } from 'rxjs'; +import { SpacesApi } from './api'; -export const createSelectHandler = (handleChange) => { - return (name) => (selectedOptions) => { - return handleChange?.({ - [name]: _.get(selectedOptions, '[0].value', null), - }); - }; +const createApiMock = (): jest.Mocked => ({ + activeSpace$: of(), + getActiveSpace: jest.fn(), +}); + +export const spacesApiMock = { + create: createApiMock, }; diff --git a/src/plugins/spaces_oss/public/api.ts b/src/plugins/spaces_oss/public/api.ts new file mode 100644 index 0000000000000..7725175a5b873 --- /dev/null +++ b/src/plugins/spaces_oss/public/api.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Observable } from 'rxjs'; +import { Space } from '../common'; + +/** + * @public + */ +export interface SpacesApi { + readonly activeSpace$: Observable; + getActiveSpace(): Promise; +} diff --git a/src/plugins/spaces_oss/public/index.ts b/src/plugins/spaces_oss/public/index.ts new file mode 100644 index 0000000000000..f6e551053ae6c --- /dev/null +++ b/src/plugins/spaces_oss/public/index.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SpacesOssPlugin } from './plugin'; + +export { SpacesOssPluginSetup, SpacesOssPluginStart } from './types'; + +export { SpacesApi } from './api'; + +export const plugin = () => new SpacesOssPlugin(); diff --git a/src/plugins/vis_type_timeseries/common/model_options.js b/src/plugins/spaces_oss/public/mocks/index.ts similarity index 64% rename from src/plugins/vis_type_timeseries/common/model_options.js rename to src/plugins/spaces_oss/public/mocks/index.ts index 22fe7a0abc842..f201ed9334804 100644 --- a/src/plugins/vis_type_timeseries/common/model_options.js +++ b/src/plugins/spaces_oss/public/mocks/index.ts @@ -17,10 +17,19 @@ * under the License. */ -export const MODEL_TYPES = { - UNWEIGHTED: 'simple', - WEIGHTED_EXPONENTIAL: 'ewma', - WEIGHTED_EXPONENTIAL_DOUBLE: 'holt', - WEIGHTED_EXPONENTIAL_TRIPLE: 'holt_winters', - WEIGHTED_LINEAR: 'linear', +import { spacesApiMock } from '../api.mock'; +import { SpacesOssPluginSetup, SpacesOssPluginStart } from '..'; + +const createSetupContract = (): jest.Mocked => ({ + registerSpacesApi: jest.fn(), +}); + +const createStartContract = (): jest.Mocked => ({ + isSpacesAvailable: true, + ...spacesApiMock.create(), +}); + +export const spacesOssPluginMock = { + createSetupContract, + createStartContract, }; diff --git a/src/plugins/spaces_oss/public/plugin.test.ts b/src/plugins/spaces_oss/public/plugin.test.ts new file mode 100644 index 0000000000000..4099c9a7eb4c0 --- /dev/null +++ b/src/plugins/spaces_oss/public/plugin.test.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { spacesApiMock } from './api.mock'; +import { SpacesOssPlugin } from './plugin'; + +describe('SpacesOssPlugin', () => { + let plugin: SpacesOssPlugin; + + beforeEach(() => { + plugin = new SpacesOssPlugin(); + }); + + describe('#setup', () => { + it('only allows the API to be registered once', async () => { + const spacesApi = spacesApiMock.create(); + const { registerSpacesApi } = plugin.setup(); + + expect(() => registerSpacesApi(spacesApi)).not.toThrow(); + + expect(() => registerSpacesApi(spacesApi)).toThrowErrorMatchingInlineSnapshot( + `"Spaces API can only be registered once"` + ); + }); + }); + + describe('#start', () => { + it('returns the spaces API if registered', async () => { + const spacesApi = spacesApiMock.create(); + const { registerSpacesApi } = plugin.setup(); + + registerSpacesApi(spacesApi); + + const { isSpacesAvailable, ...api } = plugin.start(); + + expect(isSpacesAvailable).toBe(true); + expect(api).toStrictEqual(spacesApi); + }); + + it('does not return the spaces API if not registered', async () => { + plugin.setup(); + + const { isSpacesAvailable, ...api } = plugin.start(); + + expect(isSpacesAvailable).toBe(false); + expect(Object.keys(api)).toHaveLength(0); + }); + }); +}); diff --git a/src/plugins/spaces_oss/public/plugin.ts b/src/plugins/spaces_oss/public/plugin.ts new file mode 100644 index 0000000000000..93b1c7696f0fb --- /dev/null +++ b/src/plugins/spaces_oss/public/plugin.ts @@ -0,0 +1,52 @@ +/* + * 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 { Plugin } from 'src/core/public'; +import { SpacesOssPluginSetup, SpacesOssPluginStart } from './types'; +import { SpacesApi } from './api'; + +export class SpacesOssPlugin implements Plugin { + private api?: SpacesApi; + + constructor() {} + + public setup() { + return { + registerSpacesApi: (provider: SpacesApi) => { + if (this.api) { + throw new Error('Spaces API can only be registered once'); + } + this.api = provider; + }, + }; + } + + public start() { + if (this.api) { + return { + isSpacesAvailable: true as true, + ...this.api!, + }; + } else { + return { + isSpacesAvailable: false as false, + }; + } + } +} diff --git a/src/plugins/data/public/query/timefilter/lib/get_force_now.ts b/src/plugins/spaces_oss/public/types.ts similarity index 60% rename from src/plugins/data/public/query/timefilter/lib/get_force_now.ts rename to src/plugins/spaces_oss/public/types.ts index fe68656f0c3aa..e089231513e23 100644 --- a/src/plugins/data/public/query/timefilter/lib/get_force_now.ts +++ b/src/plugins/spaces_oss/public/types.ts @@ -17,18 +17,23 @@ * under the License. */ -import { parseQueryString } from './parse_querystring'; +import { SpacesApi } from './api'; -/** @internal */ -export function getForceNow() { - const forceNow = parseQueryString().forceNow as string; - if (!forceNow) { - return; - } +interface SpacesAvailableStartContract extends SpacesApi { + isSpacesAvailable: true; +} + +interface SpacesUnavailableStartContract { + isSpacesAvailable: false; +} - const ticks = Date.parse(forceNow); - if (isNaN(ticks)) { - throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`); - } - return new Date(ticks); +export interface SpacesOssPluginSetup { + /** + * Register a provider for the Spaces API. + * + * Only one provider can be registered, subsequent calls to this method will fail. + */ + registerSpacesApi(provider: SpacesApi): void; } + +export type SpacesOssPluginStart = SpacesAvailableStartContract | SpacesUnavailableStartContract; diff --git a/src/plugins/spaces_oss/tsconfig.json b/src/plugins/spaces_oss/tsconfig.json new file mode 100644 index 0000000000000..0cc82d7e5d124 --- /dev/null +++ b/src/plugins/spaces_oss/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + ] +} diff --git a/src/plugins/telemetry_management_section/tsconfig.json b/src/plugins/telemetry_management_section/tsconfig.json new file mode 100644 index 0000000000000..48e40814b8570 --- /dev/null +++ b/src/plugins/telemetry_management_section/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "../../../typings/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../telemetry/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json"}, + { "path": "../ui_actions/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../bfetch/tsconfig.json"}, + { "path": "../data/tsconfig.json"}, + { "path": "../advanced_settings/tsconfig.json" }, + { "path": "../management/tsconfig.json"} + ] +} diff --git a/src/plugins/timelion/public/services/_saved_sheet.ts b/src/plugins/timelion/public/services/_saved_sheet.ts index 3fe66fabebe73..eafc8068fbfd1 100644 --- a/src/plugins/timelion/public/services/_saved_sheet.ts +++ b/src/plugins/timelion/public/services/_saved_sheet.ts @@ -69,5 +69,5 @@ export function createSavedSheetClass(savedObjects: SavedObjectsStart, config: I } } - return SavedSheet; + return SavedSheet as unknown; } diff --git a/src/plugins/timelion/tsconfig.json b/src/plugins/timelion/tsconfig.json new file mode 100644 index 0000000000000..5b96d69a878ea --- /dev/null +++ b/src/plugins/timelion/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../navigation/tsconfig.json" }, + { "path": "../vis_type_timelion/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_default_editor/public/components/controls/palette_picker.test.tsx b/src/plugins/vis_default_editor/public/components/controls/palette_picker.test.tsx new file mode 100644 index 0000000000000..1b4d7e060296a --- /dev/null +++ b/src/plugins/vis_default_editor/public/components/controls/palette_picker.test.tsx @@ -0,0 +1,59 @@ +/* + * 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 React from 'react'; +import { mountWithIntl } from '@kbn/test/jest'; +import { ReactWrapper } from 'enzyme'; +import { PalettePicker, PalettePickerProps } from './palette_picker'; +import { chartPluginMock } from '../../../../charts/public/mocks'; +import { EuiColorPalettePicker } from '@elastic/eui'; + +describe('PalettePicker', function () { + let props: PalettePickerProps<'palette'>; + let component: ReactWrapper>; + + beforeAll(() => { + props = { + palettes: chartPluginMock.createPaletteRegistry(), + paramName: 'palette', + activePalette: { + type: 'palette', + name: 'kibana_palette', + }, + setPalette: jest.fn(), + }; + }); + + it('renders the EuiPalettePicker', () => { + component = mountWithIntl(); + expect(component.find(EuiColorPalettePicker).length).toBe(1); + }); + + it('renders the default palette if not activePalette is given', function () { + const { activePalette, ...newProps } = props; + component = mountWithIntl(); + const palettePicker = component.find(EuiColorPalettePicker); + expect(palettePicker.props().valueOfSelected).toBe('default'); + }); + + it('renders the activePalette palette if given', function () { + component = mountWithIntl(); + const palettePicker = component.find(EuiColorPalettePicker); + expect(palettePicker.props().valueOfSelected).toBe('kibana_palette'); + }); +}); diff --git a/src/plugins/vis_default_editor/public/components/controls/palette_picker.tsx b/src/plugins/vis_default_editor/public/components/controls/palette_picker.tsx new file mode 100644 index 0000000000000..8985ded413d46 --- /dev/null +++ b/src/plugins/vis_default_editor/public/components/controls/palette_picker.tsx @@ -0,0 +1,75 @@ +/* + * 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 React from 'react'; +import { PaletteOutput, PaletteRegistry } from 'src/plugins/charts/public'; +import { EuiColorPalettePicker } from '@elastic/eui'; +import { EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export interface PalettePickerProps { + activePalette?: PaletteOutput; + palettes: PaletteRegistry; + paramName: ParamName; + setPalette: (paramName: ParamName, value: PaletteOutput) => void; +} + +export function PalettePicker({ + activePalette, + palettes, + paramName, + setPalette, +}: PalettePickerProps) { + return ( + + !internal) + .map(({ id, title, getColors }) => { + return { + value: id, + title, + type: 'fixed', + palette: getColors( + 10, + id === activePalette?.name ? activePalette?.params : undefined + ), + }; + })} + onChange={(newPalette) => { + setPalette(paramName, { + type: 'palette', + name: newPalette, + }); + }} + valueOfSelected={activePalette?.name || 'default'} + selectionDisplay={'palette'} + /> + + ); +} diff --git a/src/plugins/vis_default_editor/public/default_editor.tsx b/src/plugins/vis_default_editor/public/default_editor.tsx index a7251acfdf75d..f5e83396136a8 100644 --- a/src/plugins/vis_default_editor/public/default_editor.tsx +++ b/src/plugins/vis_default_editor/public/default_editor.tsx @@ -23,8 +23,8 @@ import 'brace/mode/json'; import React, { useEffect, useRef, useState, useCallback } from 'react'; import { EventEmitter } from 'events'; -import { EditorRenderProps } from 'src/plugins/visualize/public'; import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public'; +import { EditorRenderProps } from 'src/plugins/visualize/public'; import { KibanaContextProvider, PanelsContainer, Panel } from '../../kibana_react/public'; import { Storage } from '../../kibana_utils/public'; diff --git a/src/plugins/vis_default_editor/public/default_editor_controller.tsx b/src/plugins/vis_default_editor/public/default_editor_controller.tsx index f44ea3e203b05..2bf1d3f9f6747 100644 --- a/src/plugins/vis_default_editor/public/default_editor_controller.tsx +++ b/src/plugins/vis_default_editor/public/default_editor_controller.tsx @@ -22,8 +22,8 @@ import { render, unmountComponentAtNode } from 'react-dom'; import { EventEmitter } from 'events'; import { EuiErrorBoundary, EuiLoadingChart } from '@elastic/eui'; -import { EditorRenderProps, IEditorController } from 'src/plugins/visualize/public'; import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public'; +import { IEditorController, EditorRenderProps } from 'src/plugins/visualize/public'; // @ts-ignore const DefaultEditor = lazy(() => import('./default_editor')); diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index 06834ab19c876..bd907095baeeb 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -23,6 +23,7 @@ import { VisDefaultEditorPlugin } from './plugin'; export { DefaultEditorController }; export { useValidation } from './components/controls/utils'; +export { PalettePicker } from './components/controls/palette_picker'; export * from './components/options'; export { RangesParamEditor, RangeValues } from './components/controls/ranges'; export * from './editor_size'; diff --git a/src/plugins/vis_default_editor/public/plugin.ts b/src/plugins/vis_default_editor/public/plugin.ts index a7a5c6146a6e8..669ed2173c4ce 100644 --- a/src/plugins/vis_default_editor/public/plugin.ts +++ b/src/plugins/vis_default_editor/public/plugin.ts @@ -30,7 +30,7 @@ export class VisDefaultEditorPlugin implements Plugin { public setup(core: CoreSetup, { visualize }: VisDefaultEditorSetupDependencies) { if (visualize) { - visualize.setDefaultEditor(DefaultEditorController); + visualize.visEditorsRegistry.registerDefault(DefaultEditorController); } } diff --git a/src/plugins/vis_default_editor/tsconfig.json b/src/plugins/vis_default_editor/tsconfig.json new file mode 100644 index 0000000000000..27bb775c2d0e8 --- /dev/null +++ b/src/plugins/vis_default_editor/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../visualize/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_markdown/kibana.json b/src/plugins/vis_type_markdown/kibana.json index 6cfedf60687ef..e14b4fe7bce96 100644 --- a/src/plugins/vis_type_markdown/kibana.json +++ b/src/plugins/vis_type_markdown/kibana.json @@ -3,6 +3,14 @@ "version": "kibana", "ui": true, "server": true, - "requiredPlugins": ["expressions", "visualizations"], - "requiredBundles": ["kibanaReact", "visualizations", "expressions", "visDefaultEditor"] + "requiredPlugins": [ + "expressions", + "visualizations" + ], + "requiredBundles": [ + "expressions", + "kibanaReact", + "visDefaultEditor", + "visualizations" + ] } diff --git a/src/plugins/vis_type_markdown/tsconfig.json b/src/plugins/vis_type_markdown/tsconfig.json new file mode 100644 index 0000000000000..d5ab89b98081b --- /dev/null +++ b/src/plugins/vis_type_markdown/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_metric/tsconfig.json b/src/plugins/vis_type_metric/tsconfig.json new file mode 100644 index 0000000000000..7441848d5a430 --- /dev/null +++ b/src/plugins/vis_type_metric/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["public/**/*", "server/**/*", "*.ts"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" } + ] +} diff --git a/src/plugins/vis_type_table/public/legacy/vis_controller.ts b/src/plugins/vis_type_table/public/legacy/vis_controller.ts index eff8e34f3e778..7584397e78dc6 100644 --- a/src/plugins/vis_type_table/public/legacy/vis_controller.ts +++ b/src/plugins/vis_type_table/public/legacy/vis_controller.ts @@ -42,8 +42,8 @@ export function getTableVisualizationControllerClass( context: PluginInitializerContext ) { return class TableVisualizationController { - private tableVisModule: IModule | undefined; - private injector: auto.IInjectorService | undefined; + tableVisModule: IModule | undefined; + injector: auto.IInjectorService | undefined; el: JQuery; $rootScope: IRootScopeService | null = null; $scope: (IScope & { [key: string]: any }) | undefined; diff --git a/src/plugins/vis_type_table/tsconfig.json b/src/plugins/vis_type_table/tsconfig.json new file mode 100644 index 0000000000000..bda86d06c0ff7 --- /dev/null +++ b/src/plugins/vis_type_table/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../share/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_tagcloud/tsconfig.json b/src/plugins/vis_type_tagcloud/tsconfig.json new file mode 100644 index 0000000000000..18bbad2257466 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_timelion/common/types.ts b/src/plugins/vis_type_timelion/common/types.ts index f7084948a14f7..fed380130b26d 100644 --- a/src/plugins/vis_type_timelion/common/types.ts +++ b/src/plugins/vis_type_timelion/common/types.ts @@ -19,7 +19,7 @@ type TimelionFunctionArgsTypes = 'seriesList' | 'number' | 'string' | 'boolean' | 'null'; -interface TimelionFunctionArgsSuggestion { +export interface TimelionFunctionArgsSuggestion { name: string; help: string; } diff --git a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts index 7a630f36b51f4..896a827f6248c 100644 --- a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts +++ b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts @@ -73,12 +73,15 @@ export function getTimelionRequestHandler({ filters, query, visParams, + searchSessionId, }: { timeRange: TimeRange; filters: Filter[]; query: Query; visParams: TimelionVisParams; + searchSessionId?: string; }): Promise { + const dataSearch = getDataSearch(); const expression = visParams.expression; if (!expression) { @@ -93,7 +96,13 @@ export function getTimelionRequestHandler({ // parse the time range client side to make sure it behaves like other charts const timeRangeBounds = timefilter.calculateBounds(timeRange); - const sessionId = getDataSearch().session.getSessionId(); + const untrackSearch = + dataSearch.session.isCurrentSession(searchSessionId) && + dataSearch.session.trackSearch({ + abort: () => { + // TODO: support search cancellations + }, + }); try { return await http.post('/api/timelion/run', { @@ -110,7 +119,9 @@ export function getTimelionRequestHandler({ interval: visParams.interval, timezone, }, - sessionId, + ...(searchSessionId && { + searchSession: dataSearch.session.getSearchOptions(searchSessionId), + }), }), }); } catch (e) { @@ -125,6 +136,11 @@ export function getTimelionRequestHandler({ } else { throw e; } + } finally { + if (untrackSearch && dataSearch.session.isCurrentSession(searchSessionId)) { + // call `untrack` if this search still belongs to current session + untrackSearch(); + } } }; } diff --git a/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts index 2e8878b11e915..d4bf27ea53819 100644 --- a/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts +++ b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts @@ -30,23 +30,21 @@ import { KibanaContext, Filter, Query, TimeRange } from '../../data/public'; type Input = KibanaContext | null; type Output = Promise>; -interface Arguments { - expression: string; - interval: string; -} - export interface TimelionRenderValue { visData: TimelionSuccessResponse; visType: 'timelion'; visParams: TimelionVisParams; } -export type TimelionVisParams = Arguments; +export interface TimelionVisParams { + expression: string; + interval: string; +} export type TimelionExpressionFunctionDefinition = ExpressionFunctionDefinition< 'timelion_vis', Input, - Arguments, + TimelionVisParams, Output >; @@ -72,7 +70,7 @@ export const getTimelionVisualizationConfig = ( help: '', }, }, - async fn(input, args) { + async fn(input, args, { getSearchSessionId }) { const timelionRequestHandler = getTimelionRequestHandler(dependencies); const visParams = { expression: args.expression, interval: args.interval }; @@ -82,6 +80,7 @@ export const getTimelionVisualizationConfig = ( query: get(input, 'query') as Query, filters: get(input, 'filters') as Filter[], visParams, + searchSessionId: getSearchSessionId(), }); response.visType = TIMELION_VIS_NAME; diff --git a/src/plugins/vis_type_timelion/server/routes/run.ts b/src/plugins/vis_type_timelion/server/routes/run.ts index 5766705d9873d..af5af35e53b3f 100644 --- a/src/plugins/vis_type_timelion/server/routes/run.ts +++ b/src/plugins/vis_type_timelion/server/routes/run.ts @@ -75,7 +75,13 @@ export function runRoute( to: schema.maybe(schema.string()), }) ), - sessionId: schema.maybe(schema.string()), + searchSession: schema.maybe( + schema.object({ + sessionId: schema.string(), + isRestore: schema.boolean({ defaultValue: false }), + isStored: schema.boolean({ defaultValue: false }), + }) + ), }), }, }, diff --git a/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js index f4ba36e4fdd67..b02baefea9919 100644 --- a/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js +++ b/src/plugins/vis_type_timelion/server/series_functions/es/es.test.js @@ -60,19 +60,26 @@ describe('es', () => { }); }); - test('should call data search with sessionId', async () => { + test('should call data search with sessionId, isRestore and isStored', async () => { tlConfig = { ...stubRequestAndServer({ rawResponse: esResponse }), request: { body: { - sessionId: 1, + searchSession: { + sessionId: '1', + isRestore: true, + isStored: false, + }, }, }, }; await invoke(es, [5], tlConfig); - expect(tlConfig.context.search.search.mock.calls[0][1]).toHaveProperty('sessionId', 1); + const res = tlConfig.context.search.search.mock.calls[0][1]; + expect(res).toHaveProperty('sessionId', '1'); + expect(res).toHaveProperty('isRestore', true); + expect(res).toHaveProperty('isStored', false); }); test('returns a seriesList', () => { diff --git a/src/plugins/vis_type_timelion/server/series_functions/es/index.js b/src/plugins/vis_type_timelion/server/series_functions/es/index.js index 24b3668b5cd3c..579563088a0a8 100644 --- a/src/plugins/vis_type_timelion/server/series_functions/es/index.js +++ b/src/plugins/vis_type_timelion/server/series_functions/es/index.js @@ -133,7 +133,7 @@ export default new Datasource('es', { .search( body, { - sessionId: tlConfig.request?.body.sessionId, + ...tlConfig.request?.body.searchSession, }, tlConfig.context ) diff --git a/src/plugins/vis_type_timelion/tsconfig.json b/src/plugins/vis_type_timelion/tsconfig.json new file mode 100644 index 0000000000000..77f97de28366d --- /dev/null +++ b/src/plugins/vis_type_timelion/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap b/src/plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap deleted file mode 100644 index 0fca2a017b911..0000000000000 --- a/src/plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`src/legacy/core_plugins/metrics/common/model_options.js MODEL_TYPES should match a snapshot of constants 1`] = ` -Object { - "UNWEIGHTED": "simple", - "WEIGHTED_EXPONENTIAL": "ewma", - "WEIGHTED_EXPONENTIAL_DOUBLE": "holt", - "WEIGHTED_EXPONENTIAL_TRIPLE": "holt_winters", - "WEIGHTED_LINEAR": "linear", -} -`; diff --git a/src/plugins/vis_type_timeseries/common/agg_lookup.test.js b/src/plugins/vis_type_timeseries/common/agg_lookup.test.ts similarity index 83% rename from src/plugins/vis_type_timeseries/common/agg_lookup.test.js rename to src/plugins/vis_type_timeseries/common/agg_lookup.test.ts index a7c5d362e669c..d61cab6229305 100644 --- a/src/plugins/vis_type_timeseries/common/agg_lookup.test.js +++ b/src/plugins/vis_type_timeseries/common/agg_lookup.test.ts @@ -18,14 +18,15 @@ */ import { isBasicAgg } from './agg_lookup'; +import { MetricsItemsSchema } from './types'; describe('aggLookup', () => { describe('isBasicAgg(metric)', () => { test('returns true for a basic metric (count)', () => { - expect(isBasicAgg({ type: 'count' })).toEqual(true); + expect(isBasicAgg({ type: 'count' } as MetricsItemsSchema)).toEqual(true); }); test('returns false for a pipeline metric (derivative)', () => { - expect(isBasicAgg({ type: 'derivative' })).toEqual(false); + expect(isBasicAgg({ type: 'derivative' } as MetricsItemsSchema)).toEqual(false); }); }); }); diff --git a/src/plugins/vis_type_timeseries/common/agg_lookup.js b/src/plugins/vis_type_timeseries/common/agg_lookup.ts similarity index 92% rename from src/plugins/vis_type_timeseries/common/agg_lookup.js rename to src/plugins/vis_type_timeseries/common/agg_lookup.ts index 0a71ab34082f8..7cdae3f55978a 100644 --- a/src/plugins/vis_type_timeseries/common/agg_lookup.js +++ b/src/plugins/vis_type_timeseries/common/agg_lookup.ts @@ -17,10 +17,11 @@ * under the License. */ -import _ from 'lodash'; +import { omit, pick, includes } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { MetricsItemsSchema } from './types'; -export const lookup = { +export const lookup: Record = { count: i18n.translate('visTypeTimeseries.aggLookup.countLabel', { defaultMessage: 'Count' }), calculation: i18n.translate('visTypeTimeseries.aggLookup.calculationLabel', { defaultMessage: 'Calculation', @@ -122,11 +123,11 @@ const pipeline = [ const byType = { _all: lookup, - pipeline: pipeline, - basic: _.omit(lookup, pipeline), - metrics: _.pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']), + pipeline, + basic: omit(lookup, pipeline), + metrics: pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']), }; -export function isBasicAgg(item) { - return _.includes(Object.keys(byType.basic), item.type); +export function isBasicAgg(item: MetricsItemsSchema) { + return includes(Object.keys(byType.basic), item.type); } diff --git a/src/plugins/vis_type_timeseries/common/calculate_label.test.js b/src/plugins/vis_type_timeseries/common/calculate_label.test.ts similarity index 56% rename from src/plugins/vis_type_timeseries/common/calculate_label.test.js rename to src/plugins/vis_type_timeseries/common/calculate_label.test.ts index a5af6d114c894..0f201d405ee0d 100644 --- a/src/plugins/vis_type_timeseries/common/calculate_label.test.js +++ b/src/plugins/vis_type_timeseries/common/calculate_label.test.ts @@ -18,66 +18,79 @@ */ import { calculateLabel } from './calculate_label'; +import type { MetricsItemsSchema } from './types'; describe('calculateLabel(metric, metrics)', () => { - test('returns "Unknown" for empty metric', () => { - expect(calculateLabel()).toEqual('Unknown'); - }); - test('returns the metric.alias if set', () => { - expect(calculateLabel({ alias: 'Example' })).toEqual('Example'); + expect(calculateLabel({ alias: 'Example' } as MetricsItemsSchema)).toEqual('Example'); }); test('returns "Count" for a count metric', () => { - expect(calculateLabel({ type: 'count' })).toEqual('Count'); + expect(calculateLabel({ type: 'count' } as MetricsItemsSchema)).toEqual('Count'); }); test('returns "Calculation" for a bucket script metric', () => { - expect(calculateLabel({ type: 'calculation' })).toEqual('Bucket Script'); + expect(calculateLabel({ type: 'calculation' } as MetricsItemsSchema)).toEqual('Bucket Script'); }); - test('returns formated label for series_agg', () => { - const label = calculateLabel({ type: 'series_agg', function: 'max' }); + test('returns formatted label for series_agg', () => { + const label = calculateLabel({ type: 'series_agg', function: 'max' } as MetricsItemsSchema); + expect(label).toEqual('Series Agg (max)'); }); - test('returns formated label for basic aggs', () => { - const label = calculateLabel({ type: 'avg', field: 'memory' }); + test('returns formatted label for basic aggs', () => { + const label = calculateLabel({ type: 'avg', field: 'memory' } as MetricsItemsSchema); + expect(label).toEqual('Average of memory'); }); - test('returns formated label for pipeline aggs', () => { - const metric = { id: 2, type: 'derivative', field: 1 }; - const metrics = [{ id: 1, type: 'max', field: 'network.out.bytes' }, metric]; + test('returns formatted label for pipeline aggs', () => { + const metric = ({ id: 2, type: 'derivative', field: 1 } as unknown) as MetricsItemsSchema; + const metrics = ([ + { id: 1, type: 'max', field: 'network.out.bytes' }, + metric, + ] as unknown) as MetricsItemsSchema[]; const label = calculateLabel(metric, metrics); + expect(label).toEqual('Derivative of Max of network.out.bytes'); }); - test('returns formated label for derivative of percentile', () => { - const metric = { id: 2, type: 'derivative', field: '1[50.0]' }; - const metrics = [{ id: 1, type: 'percentile', field: 'network.out.bytes' }, metric]; + test('returns formatted label for derivative of percentile', () => { + const metric = ({ + id: 2, + type: 'derivative', + field: '1[50.0]', + } as unknown) as MetricsItemsSchema; + const metrics = ([ + { id: 1, type: 'percentile', field: 'network.out.bytes' }, + metric, + ] as unknown) as MetricsItemsSchema[]; const label = calculateLabel(metric, metrics); + expect(label).toEqual('Derivative of Percentile of network.out.bytes (50.0)'); }); - test('returns formated label for pipeline aggs (deep)', () => { - const metric = { id: 3, type: 'derivative', field: 2 }; - const metrics = [ + test('returns formatted label for pipeline aggs (deep)', () => { + const metric = ({ id: 3, type: 'derivative', field: 2 } as unknown) as MetricsItemsSchema; + const metrics = ([ { id: 1, type: 'max', field: 'network.out.bytes' }, { id: 2, type: 'moving_average', field: 1 }, metric, - ]; + ] as unknown) as MetricsItemsSchema[]; const label = calculateLabel(metric, metrics); + expect(label).toEqual('Derivative of Moving Average of Max of network.out.bytes'); }); - test('returns formated label for pipeline aggs uses alias for field metric', () => { - const metric = { id: 2, type: 'derivative', field: 1 }; - const metrics = [ + test('returns formatted label for pipeline aggs uses alias for field metric', () => { + const metric = ({ id: 2, type: 'derivative', field: 1 } as unknown) as MetricsItemsSchema; + const metrics = ([ { id: 1, type: 'max', field: 'network.out.bytes', alias: 'Outbound Traffic' }, metric, - ]; + ] as unknown) as MetricsItemsSchema[]; const label = calculateLabel(metric, metrics); + expect(label).toEqual('Derivative of Outbound Traffic'); }); }); diff --git a/src/plugins/vis_type_timeseries/common/calculate_label.js b/src/plugins/vis_type_timeseries/common/calculate_label.ts similarity index 84% rename from src/plugins/vis_type_timeseries/common/calculate_label.js rename to src/plugins/vis_type_timeseries/common/calculate_label.ts index 96e9fa0825b25..33a1fbe6879ae 100644 --- a/src/plugins/vis_type_timeseries/common/calculate_label.js +++ b/src/plugins/vis_type_timeseries/common/calculate_label.ts @@ -18,8 +18,9 @@ */ import { includes, startsWith } from 'lodash'; -import { lookup } from './agg_lookup'; import { i18n } from '@kbn/i18n'; +import { lookup } from './agg_lookup'; +import { MetricsItemsSchema, SanitizedFieldType } from './types'; const paths = [ 'cumulative_sum', @@ -36,7 +37,15 @@ const paths = [ 'positive_only', ]; -export function calculateLabel(metric, metrics) { +export const extractFieldLabel = (fields: SanitizedFieldType[], name: string) => { + return fields.find((f) => f.name === name)?.label ?? name; +}; + +export const calculateLabel = ( + metric: MetricsItemsSchema, + metrics: MetricsItemsSchema[] = [], + fields: SanitizedFieldType[] = [] +): string => { if (!metric) { return i18n.translate('visTypeTimeseries.calculateLabel.unknownLabel', { defaultMessage: 'Unknown', @@ -73,7 +82,7 @@ export function calculateLabel(metric, metrics) { if (metric.type === 'positive_rate') { return i18n.translate('visTypeTimeseries.calculateLabel.positiveRateLabel', { defaultMessage: 'Counter Rate of {field}', - values: { field: metric.field }, + values: { field: extractFieldLabel(fields, metric.field!) }, }); } if (metric.type === 'static') { @@ -84,15 +93,15 @@ export function calculateLabel(metric, metrics) { } if (includes(paths, metric.type)) { - const targetMetric = metrics.find((m) => startsWith(metric.field, m.id)); - const targetLabel = calculateLabel(targetMetric, metrics); + const targetMetric = metrics.find((m) => startsWith(metric.field!, m.id)); + const targetLabel = calculateLabel(targetMetric!, metrics, fields); // For percentiles we need to parse the field id to extract the percentile // the user configured in the percentile aggregation and specified in the // submetric they selected. This applies only to pipeline aggs. if (targetMetric && targetMetric.type === 'percentile') { const percentileValueMatch = /\[([0-9\.]+)\]$/; - const matches = metric.field.match(percentileValueMatch); + const matches = metric.field!.match(percentileValueMatch); if (matches) { return i18n.translate( 'visTypeTimeseries.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel', @@ -115,6 +124,9 @@ export function calculateLabel(metric, metrics) { return i18n.translate('visTypeTimeseries.calculateLabel.lookupMetricTypeOfMetricFieldRankLabel', { defaultMessage: '{lookupMetricType} of {metricField}', - values: { lookupMetricType: lookup[metric.type], metricField: metric.field }, + values: { + lookupMetricType: lookup[metric.type], + metricField: extractFieldLabel(fields, metric.field!), + }, }); -} +}; diff --git a/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.js b/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts similarity index 73% rename from src/plugins/vis_type_timeseries/common/extract_index_patterns.test.js rename to src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts index 385c0b58d12fd..69cbd9c3fe0b6 100644 --- a/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.js +++ b/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts @@ -18,16 +18,13 @@ */ import { extractIndexPatterns } from './extract_index_patterns'; +import { PanelSchema } from './types'; describe('extractIndexPatterns(vis)', () => { - let visParams; - let visFields; + let panel: PanelSchema; beforeEach(() => { - visFields = { - '*': [], - }; - visParams = { + panel = { index_pattern: '*', series: [ { @@ -40,25 +37,10 @@ describe('extractIndexPatterns(vis)', () => { }, ], annotations: [{ index_pattern: 'notes-*' }, { index_pattern: 'example-1-*' }], - }; + } as PanelSchema; }); test('should return index patterns', () => { - visFields = {}; - - expect(extractIndexPatterns(visParams, visFields)).toEqual([ - '*', - 'example-1-*', - 'example-2-*', - 'notes-*', - ]); - }); - - test('should return index patterns that do not exist in visFields', () => { - expect(extractIndexPatterns(visParams, visFields)).toEqual([ - 'example-1-*', - 'example-2-*', - 'notes-*', - ]); + expect(extractIndexPatterns(panel, '')).toEqual(['*', 'example-1-*', 'example-2-*', 'notes-*']); }); }); diff --git a/src/plugins/vis_type_timeseries/common/extract_index_patterns.js b/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts similarity index 73% rename from src/plugins/vis_type_timeseries/common/extract_index_patterns.js rename to src/plugins/vis_type_timeseries/common/extract_index_patterns.ts index 3fb005b477199..ba30f6da02321 100644 --- a/src/plugins/vis_type_timeseries/common/extract_index_patterns.js +++ b/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts @@ -17,17 +17,21 @@ * under the License. */ import { uniq } from 'lodash'; +import { PanelSchema } from '../common/types'; -export function extractIndexPatterns(panel, excludedFields = {}) { - const patterns = []; +export function extractIndexPatterns( + panel: PanelSchema, + defaultIndex?: PanelSchema['default_index_pattern'] +) { + const patterns: string[] = []; - if (!excludedFields[panel.index_pattern]) { + if (panel.index_pattern) { patterns.push(panel.index_pattern); } panel.series.forEach((series) => { const indexPattern = series.series_index_pattern; - if (indexPattern && series.override_index_pattern && !excludedFields[indexPattern]) { + if (indexPattern && series.override_index_pattern) { patterns.push(indexPattern); } }); @@ -35,15 +39,15 @@ export function extractIndexPatterns(panel, excludedFields = {}) { if (panel.annotations) { panel.annotations.forEach((item) => { const indexPattern = item.index_pattern; - if (indexPattern && !excludedFields[indexPattern]) { + if (indexPattern) { patterns.push(indexPattern); } }); } - if (patterns.length === 0) { - patterns.push(''); + if (patterns.length === 0 && defaultIndex) { + patterns.push(defaultIndex); } - return uniq(patterns).sort(); + return uniq(patterns).sort(); } diff --git a/src/plugins/vis_type_timeseries/common/field_types.ts b/src/plugins/vis_type_timeseries/common/field_types.ts new file mode 100644 index 0000000000000..d12d4fe831659 --- /dev/null +++ b/src/plugins/vis_type_timeseries/common/field_types.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export enum FIELD_TYPES { + BOOLEAN = 'boolean', + DATE = 'date', + GEO = 'geo_point', + NUMBER = 'number', + STRING = 'string', +} diff --git a/src/plugins/vis_type_timeseries/common/model_options.ts b/src/plugins/vis_type_timeseries/common/model_options.ts new file mode 100644 index 0000000000000..1eefc92e7615a --- /dev/null +++ b/src/plugins/vis_type_timeseries/common/model_options.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export enum MODEL_TYPES { + UNWEIGHTED = 'simple', + WEIGHTED_EXPONENTIAL = 'ewma', + WEIGHTED_EXPONENTIAL_DOUBLE = 'holt', + WEIGHTED_EXPONENTIAL_TRIPLE = 'holt_winters', + WEIGHTED_LINEAR = 'linear', +} diff --git a/src/plugins/vis_type_timeseries/common/timerange_data_modes.js b/src/plugins/vis_type_timeseries/common/timerange_data_modes.ts similarity index 91% rename from src/plugins/vis_type_timeseries/common/timerange_data_modes.js rename to src/plugins/vis_type_timeseries/common/timerange_data_modes.ts index 7d69d36f213b7..7c8755baf3164 100644 --- a/src/plugins/vis_type_timeseries/common/timerange_data_modes.js +++ b/src/plugins/vis_type_timeseries/common/timerange_data_modes.ts @@ -22,19 +22,19 @@ * @constant * @public */ -export const TIME_RANGE_DATA_MODES = { +export enum TIME_RANGE_DATA_MODES { /** * Entire timerange mode will match all the documents selected in the * timerange timepicker */ - ENTIRE_TIME_RANGE: 'entire_time_range', + ENTIRE_TIME_RANGE = 'entire_time_range', /** * Last value mode will match only the documents for the specified interval * from the end of the timerange. */ - LAST_VALUE: 'last_value', -}; + LAST_VALUE = 'last_value', +} /** * Key for getting the Time Range mode from the Panel configuration object. diff --git a/src/plugins/vis_type_timeseries/common/to_percentile_number.js b/src/plugins/vis_type_timeseries/common/to_percentile_number.ts similarity index 94% rename from src/plugins/vis_type_timeseries/common/to_percentile_number.js rename to src/plugins/vis_type_timeseries/common/to_percentile_number.ts index b81133db8f084..51d60b99089eb 100644 --- a/src/plugins/vis_type_timeseries/common/to_percentile_number.js +++ b/src/plugins/vis_type_timeseries/common/to_percentile_number.ts @@ -18,5 +18,5 @@ */ const percentileNumberTest = /\d+\.\d+/; -export const toPercentileNumber = (value) => +export const toPercentileNumber = (value: string) => percentileNumberTest.test(`${value}`) ? value : `${value}.0`; diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index f8e1b740fc646..754a338811df9 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -18,7 +18,7 @@ */ import { TypeOf } from '@kbn/config-schema'; -import { metricsItems, panel, seriesItems, visPayloadSchema } from './vis_schema'; +import { metricsItems, panel, seriesItems, visPayloadSchema, fieldObject } from './vis_schema'; import { PANEL_TYPES } from './panel_types'; import { TimeseriesUIRestrictions } from './ui_restrictions'; @@ -26,6 +26,7 @@ export type SeriesItemsSchema = TypeOf; export type MetricsItemsSchema = TypeOf; export type PanelSchema = TypeOf; export type VisPayload = TypeOf; +export type FieldObject = TypeOf; interface PanelData { id: string; @@ -53,3 +54,9 @@ export type TimeseriesVisData = SeriesData & { */ series?: unknown[]; }; + +export interface SanitizedFieldType { + name: string; + type: string; + label?: string; +} diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index a90fa752ad7dc..e3773aada4c19 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -47,6 +47,8 @@ const numberOptionalOrEmptyString = schema.maybe( schema.oneOf([numberOptional, schema.literal('')]) ); +export const fieldObject = stringOptionalNullable; + const annotationsItems = schema.object({ color: stringOptionalNullable, fields: stringOptionalNullable, @@ -58,7 +60,7 @@ const annotationsItems = schema.object({ index_pattern: stringOptionalNullable, query_string: schema.maybe(queryObject), template: stringOptionalNullable, - time_field: stringOptionalNullable, + time_field: fieldObject, }); const backgroundColorRulesItems = schema.object({ @@ -77,8 +79,9 @@ const gaugeColorRulesItems = schema.object({ value: schema.maybe(schema.nullable(schema.number())), }); export const metricsItems = schema.object({ - field: stringOptionalNullable, + field: fieldObject, id: stringRequired, + alias: stringOptionalNullable, metric_agg: stringOptionalNullable, numerator: schema.maybe(queryObject), denominator: schema.maybe(queryObject), @@ -98,7 +101,7 @@ export const metricsItems = schema.object({ variables: schema.maybe( schema.arrayOf( schema.object({ - field: stringOptionalNullable, + field: fieldObject, id: stringRequired, name: stringOptionalNullable, }) @@ -109,7 +112,7 @@ export const metricsItems = schema.object({ schema.arrayOf( schema.object({ id: stringRequired, - field: stringOptionalNullable, + field: fieldObject, mode: schema.oneOf([schema.literal('line'), schema.literal('band')]), shade: schema.oneOf([numberOptional, stringOptionalNullable]), value: schema.maybe(schema.oneOf([numberOptional, stringOptionalNullable])), @@ -123,7 +126,7 @@ export const metricsItems = schema.object({ size: stringOrNumberOptionalNullable, agg_with: stringOptionalNullable, order: stringOptionalNullable, - order_by: stringOptionalNullable, + order_by: fieldObject, }); const splitFiltersItems = schema.object({ @@ -134,7 +137,7 @@ const splitFiltersItems = schema.object({ }); export const seriesItems = schema.object({ - aggregate_by: stringOptionalNullable, + aggregate_by: fieldObject, aggregate_function: stringOptionalNullable, axis_position: stringRequired, axis_max: stringOrNumberOptionalNullable, @@ -176,7 +179,7 @@ export const seriesItems = schema.object({ seperate_axis: numberIntegerOptional, series_index_pattern: stringOptionalNullable, series_max_bars: numberIntegerOptional, - series_time_field: stringOptionalNullable, + series_time_field: fieldObject, series_interval: stringOptionalNullable, series_drop_last_bucket: numberIntegerOptional, split_color_mode: stringOptionalNullable, @@ -184,7 +187,7 @@ export const seriesItems = schema.object({ split_mode: stringRequired, stacked: stringRequired, steps: numberIntegerOptional, - terms_field: stringOptionalNullable, + terms_field: fieldObject, terms_order_by: stringOptionalNullable, terms_size: stringOptionalNullable, terms_direction: stringOptionalNullable, @@ -241,7 +244,7 @@ export const panel = schema.object({ markdown_vertical_align: stringOptionalNullable, markdown_less: stringOptionalNullable, markdown_css: stringOptionalNullable, - pivot_id: stringOptionalNullable, + pivot_id: fieldObject, pivot_label: stringOptionalNullable, pivot_type: stringOptionalNullable, pivot_rows: stringOptionalNullable, @@ -251,7 +254,7 @@ export const panel = schema.object({ tooltip_mode: schema.maybe( schema.oneOf([schema.literal('show_all'), schema.literal('show_focused')]) ), - time_field: stringOptionalNullable, + time_field: fieldObject, time_range_mode: stringOptionalNullable, type: schema.oneOf([ schema.literal('table'), @@ -281,5 +284,12 @@ export const visPayloadSchema = schema.object({ min: stringRequired, max: stringRequired, }), - sessionId: schema.maybe(schema.string()), + + searchSession: schema.maybe( + schema.object({ + sessionId: schema.string(), + isRestore: schema.boolean({ defaultValue: false }), + isStored: schema.boolean({ defaultValue: false }), + }) + ), }); diff --git a/src/plugins/vis_type_timeseries/kibana.json b/src/plugins/vis_type_timeseries/kibana.json index f2284726c463f..242b62a2c5ee4 100644 --- a/src/plugins/vis_type_timeseries/kibana.json +++ b/src/plugins/vis_type_timeseries/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations"], + "requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize"], "optionalPlugins": ["usageCollection"], "requiredBundles": ["kibanaUtils", "kibanaReact"] } diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg.tsx index e5236c3833b19..f027e52a9220d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg.tsx @@ -59,6 +59,10 @@ export function Agg(props: AggProps) { ...props.style, }; + const indexPattern = + (props.series.override_index_pattern && props.series.series_index_pattern) || + props.panel.index_pattern; + return (
    diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/calculation.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/calculation.js index 5bf4fb55ee5e5..7d8e71f9e002d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/calculation.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/calculation.js @@ -44,7 +44,7 @@ const checkModel = (model) => Array.isArray(model.variables) && model.script !== export function CalculationAgg(props) { const htmlId = htmlIdGenerator(); - const { siblings, model } = props; + const { siblings, model, indexPattern, fields } = props; const handleChange = createChangeHandler(props.onChange, model); const handleSelectChange = createSelectHandler(handleChange); @@ -97,6 +97,8 @@ export function CalculationAgg(props) { @@ -93,6 +95,7 @@ export function CumulativeSumAgg(props) { CumulativeSumAgg.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/derivative.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/derivative.js index fa1289dc74c72..c07e7ae024bb2 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/derivative.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/derivative.js @@ -38,7 +38,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; export const DerivativeAgg = (props) => { - const { siblings } = props; + const { siblings, fields, indexPattern } = props; const defaults = { unit: '' }; const model = { ...defaults, ...props.model }; @@ -91,6 +91,7 @@ export const DerivativeAgg = (props) => { onChange={handleSelectChange('field')} metrics={siblings} metric={model} + fields={fields[indexPattern]} value={model.field} exclude={[METRIC_TYPES.TOP_HIT]} fullWidth @@ -120,6 +121,7 @@ export const DerivativeAgg = (props) => { DerivativeAgg.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.js deleted file mode 100644 index b1ff749494b10..0000000000000 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import PropTypes from 'prop-types'; -import React from 'react'; -import { EuiComboBox } from '@elastic/eui'; -import { injectI18n } from '@kbn/i18n/react'; -import { isFieldEnabled } from '../../lib/check_ui_restrictions'; -import { i18n } from '@kbn/i18n'; - -const isFieldTypeEnabled = (fieldRestrictions, fieldType) => - fieldRestrictions.length ? fieldRestrictions.includes(fieldType) : true; - -function FieldSelectUi({ - type, - fields, - indexPattern, - value, - onChange, - disabled, - restrict, - placeholder, - uiRestrictions, - ...rest -}) { - if (type === 'count') { - return null; - } - - const selectedOptions = []; - const options = Object.values( - (fields[indexPattern] || []).reduce((acc, field) => { - if ( - isFieldTypeEnabled(restrict, field.type) && - isFieldEnabled(field.name, type, uiRestrictions) - ) { - const item = { - label: field.name, - value: field.name, - }; - - if (acc[field.type]) { - acc[field.type].options.push(item); - } else { - acc[field.type] = { - options: [item], - label: field.type, - }; - } - - if (value === item.value) { - selectedOptions.push(item); - } - } - - return acc; - }, {}) - ); - - if (onChange && value && !selectedOptions.length) { - onChange(); - } - - return ( - - ); -} - -FieldSelectUi.defaultProps = { - indexPattern: '', - disabled: false, - restrict: [], - placeholder: i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', { - defaultMessage: 'Select field...', - }), -}; - -FieldSelectUi.propTypes = { - disabled: PropTypes.bool, - fields: PropTypes.object, - id: PropTypes.string, - indexPattern: PropTypes.string, - onChange: PropTypes.func, - restrict: PropTypes.array, - type: PropTypes.string, - value: PropTypes.string, - uiRestrictions: PropTypes.object, - placeholder: PropTypes.string, -}; - -export const FieldSelect = injectI18n(FieldSelectUi); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx new file mode 100644 index 0000000000000..559db6dac8155 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx @@ -0,0 +1,139 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiComboBox, EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; +import { METRIC_TYPES } from '../../../../common/metric_types'; + +import type { SanitizedFieldType } from '../../../../common/types'; +import type { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions'; + +// @ts-ignore +import { isFieldEnabled } from '../../lib/check_ui_restrictions'; + +interface FieldSelectProps { + type: string; + fields: Record; + indexPattern: string; + value: string; + onChange: (options: Array>) => void; + disabled?: boolean; + restrict?: string[]; + placeholder?: string; + uiRestrictions?: TimeseriesUIRestrictions; + 'data-test-subj'?: string; +} + +const defaultPlaceholder = i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', { + defaultMessage: 'Select field...', +}); + +const isFieldTypeEnabled = (fieldRestrictions: string[], fieldType: string) => + fieldRestrictions.length ? fieldRestrictions.includes(fieldType) : true; + +const sortByLabel = (a: EuiComboBoxOptionOption, b: EuiComboBoxOptionOption) => { + const getNormalizedString = (option: EuiComboBoxOptionOption) => + (option.label || '').toLowerCase(); + + return getNormalizedString(a).localeCompare(getNormalizedString(b)); +}; + +export function FieldSelect({ + type, + fields, + indexPattern = '', + value = '', + onChange, + disabled = false, + restrict = [], + placeholder = defaultPlaceholder, + uiRestrictions, + 'data-test-subj': dataTestSubj = 'metricsIndexPatternFieldsSelect', +}: FieldSelectProps) { + if (type === METRIC_TYPES.COUNT) { + return null; + } + + const selectedOptions: Array> = []; + let newPlaceholder = placeholder; + const groupedOptions: EuiComboBoxProps['options'] = Object.values( + (fields[indexPattern] || []).reduce>>( + (acc, field) => { + if (placeholder === field?.name) { + newPlaceholder = field.label ?? field.name; + } + + if ( + isFieldTypeEnabled(restrict, field.type) && + isFieldEnabled(field.name, type, uiRestrictions) + ) { + const item: EuiComboBoxOptionOption = { + value: field.name, + label: field.label ?? field.name, + }; + + const fieldTypeOptions = acc[field.type]?.options; + + if (fieldTypeOptions) { + fieldTypeOptions.push(item); + } else { + acc[field.type] = { + options: [item], + label: field.type, + }; + } + + if (value === item.value) { + selectedOptions.push(item); + } + } + + return acc; + }, + {} + ) + ); + + // sort groups + groupedOptions.sort(sortByLabel); + + // sort items + groupedOptions.forEach((group) => { + if (Array.isArray(group.options)) { + group.options.sort(sortByLabel); + } + }); + + if (value && !selectedOptions.length) { + onChange([]); + } + + return ( + + ); +} diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js index 1c7ab65ecd298..06887f67db84d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js @@ -24,6 +24,7 @@ import { FieldSelect } from './field_select'; import { AggRow } from './agg_row'; import { createChangeHandler } from '../lib/create_change_handler'; import { createSelectHandler } from '../lib/create_select_handler'; + import { htmlIdGenerator, EuiFlexGroup, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/math.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/math.js index 20fc88ba724bc..dd64d27fed918 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/math.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/math.js @@ -42,7 +42,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; const checkModel = (model) => Array.isArray(model.variables) && model.script !== undefined; export function MathAgg(props) { - const { siblings, model } = props; + const { siblings, model, fields, indexPattern } = props; const htmlId = htmlIdGenerator(); const handleChange = createChangeHandler(props.onChange, model); @@ -95,6 +95,8 @@ export function MathAgg(props) { { - if (includes(exclude, metric.type)) return false; + if (exclude.includes(metric.type)) { + return false; + } switch (restrict) { case 'basic': - return includes(basicAggs, metric.type); + return basicAggs.includes(metric.type); default: return true; } @@ -55,21 +57,20 @@ export function filterRows(includeSiblings) { }; } -function MetricSelectUi(props) { +export function MetricSelect(props) { const { additionalOptions, restrict, metric, + fields, metrics, onChange, value, exclude, includeSiblings, clearable, - intl, ...rest } = props; - const calculatedMetrics = metrics.filter(createTypeFilter(restrict, exclude)); const siblings = calculateSiblings(calculatedMetrics, metric); @@ -80,7 +81,7 @@ function MetricSelectUi(props) { const percentileOptions = siblings .filter((row) => /^percentile/.test(row.type)) .reduce((acc, row) => { - const label = calculateLabel(row, calculatedMetrics); + const label = calculateLabel(row, calculatedMetrics, fields); switch (row.type) { case METRIC_TYPES.PERCENTILE_RANK: @@ -110,7 +111,7 @@ function MetricSelectUi(props) { }, []); const options = siblings.filter(filterRows(includeSiblings)).map((row) => { - const label = calculateLabel(row, calculatedMetrics); + const label = calculateLabel(row, calculatedMetrics, fields); return { value: row.id, label }; }); const allOptions = [...options, ...additionalOptions, ...percentileOptions]; @@ -122,8 +123,7 @@ function MetricSelectUi(props) { return ( type === MODEL_TYPES.WEIGHTED_EXPONENTIAL_TRIPLE && period * 2 > window; export const MovingAverageAgg = (props) => { - const { siblings } = props; + const { siblings, fields, indexPattern } = props; const model = { ...DEFAULTS, ...props.model }; const modelOptions = [ @@ -153,6 +153,7 @@ export const MovingAverageAgg = (props) => { onChange={handleSelectChange('field')} metrics={siblings} metric={model} + fields={fields[indexPattern]} value={model.field} exclude={[METRIC_TYPES.TOP_HIT]} /> @@ -315,6 +316,7 @@ export const MovingAverageAgg = (props) => { MovingAverageAgg.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx index f78df9b1ddef4..9de0344f92cc6 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx @@ -40,8 +40,8 @@ import { createNumberHandler } from '../../lib/create_number_handler'; import { AggRow } from '../agg_row'; import { PercentileRankValues } from './percentile_rank_values'; -import { IFieldType, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -import { MetricsItemsSchema, PanelSchema, SeriesItemsSchema } from '../../../../../common/types'; +import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; +import { MetricsItemsSchema, PanelSchema, SanitizedFieldType } from '../../../../../common/types'; import { DragHandleProps } from '../../../../types'; import { PercentileHdr } from '../percentile_hdr'; @@ -49,10 +49,10 @@ const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; interface PercentileRankAggProps { disableDelete: boolean; - fields: IFieldType[]; + fields: Record; + indexPattern: string; model: MetricsItemsSchema; panel: PanelSchema; - series: SeriesItemsSchema; siblings: MetricsItemsSchema[]; dragHandleProps: DragHandleProps; onAdd(): void; @@ -61,12 +61,10 @@ interface PercentileRankAggProps { } export const PercentileRankAgg = (props: PercentileRankAggProps) => { - const { series, panel, fields } = props; + const { panel, fields, indexPattern } = props; const defaults = { values: [''] }; const model = { ...defaults, ...props.model }; - const indexPattern = - (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; const htmlId = htmlIdGenerator(); const isTablePanel = panel.type === 'table'; const handleChange = createChangeHandler(props.onChange, model); @@ -79,7 +77,6 @@ export const PercentileRankAgg = (props: PercentileRankAggProps) => { values, }); }; - return ( { type={model.type} restrict={RESTRICT_FIELDS} indexPattern={indexPattern} - value={model.field} + value={model.field ?? ''} onChange={handleSelectChange('field')} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_only.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_only.js index 6ca5fa8e7447f..481a9cbd22ea0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_only.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_only.js @@ -36,7 +36,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; export const PositiveOnlyAgg = (props) => { - const { siblings } = props; + const { siblings, fields, indexPattern } = props; const defaults = { unit: '' }; const model = { ...defaults, ...props.model }; @@ -85,6 +85,7 @@ export const PositiveOnlyAgg = (props) => { onChange={handleSelectChange('field')} metrics={siblings} metric={model} + fields={fields[indexPattern]} value={model.field} exclude={[METRIC_TYPES.TOP_HIT]} /> @@ -98,6 +99,7 @@ export const PositiveOnlyAgg = (props) => { PositiveOnlyAgg.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/serial_diff.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/serial_diff.js index e3a0c74273539..31ad0c432bc2d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/serial_diff.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/serial_diff.js @@ -37,7 +37,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; export const SerialDiffAgg = (props) => { - const { siblings } = props; + const { siblings, fields, indexPattern } = props; const defaults = { lag: '' }; const model = { ...defaults, ...props.model }; @@ -87,6 +87,7 @@ export const SerialDiffAgg = (props) => { onChange={handleSelectChange('field')} metrics={siblings} metric={model} + fields={fields[indexPattern]} value={model.field} exclude={[METRIC_TYPES.TOP_HIT]} /> @@ -125,6 +126,7 @@ export const SerialDiffAgg = (props) => { SerialDiffAgg.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js index b882981f6b5c7..fb8b31834048a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js @@ -37,8 +37,10 @@ import { getSupportedFieldsByMetricType } from '../lib/get_supported_fields_by_m export function StandardAgg(props) { const { model, panel, series, fields, uiRestrictions } = props; + const handleChange = createChangeHandler(props.onChange, model); const handleSelectChange = createSelectHandler(handleChange); + const restrictFields = getSupportedFieldsByMetricType(model.type); const indexPattern = (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_sibling.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_sibling.js index bed5e9caa9f87..456e03eeea1c9 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_sibling.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_sibling.js @@ -40,7 +40,7 @@ import { import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; const StandardSiblingAggUi = (props) => { - const { siblings, intl } = props; + const { siblings, intl, fields, indexPattern } = props; const defaults = { sigma: '' }; const model = { ...defaults, ...props.model }; const htmlId = htmlIdGenerator(); @@ -158,6 +158,7 @@ const StandardSiblingAggUi = (props) => { onChange={handleSelectChange('field')} exclude={[METRIC_TYPES.PERCENTILE, METRIC_TYPES.TOP_HIT]} metrics={siblings} + fields={fields[indexPattern]} metric={model} value={model.field} /> @@ -173,6 +174,7 @@ const StandardSiblingAggUi = (props) => { StandardSiblingAggUi.propTypes = { disableDelete: PropTypes.bool, fields: PropTypes.object, + indexPattern: PropTypes.string, model: PropTypes.object, onAdd: PropTypes.func, onChange: PropTypes.func, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/vars.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/vars.js index 15b02b067e353..bae839fe9ad11 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/vars.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/vars.js @@ -70,6 +70,7 @@ export class CalculationVars extends Component { metrics={this.props.metrics} metric={this.props.model} value={row.field} + fields={this.props.fields[this.props.indexPattern]} includeSiblings={this.props.includeSiblings} exclude={this.props.exclude} /> @@ -105,6 +106,8 @@ CalculationVars.defaultProps = { }; CalculationVars.propTypes = { + fields: PropTypes.object, + indexPattern: PropTypes.string, metrics: PropTypes.array, model: PropTypes.object, name: PropTypes.string, diff --git a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js index 3d38aa72fc271..dcdc2324c9b0a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js @@ -74,6 +74,7 @@ export class AnnotationsEditor extends Component { handleChange(_.assign({}, item, part)); }; } + handleQueryChange = (model, filter) => { const part = { query_string: filter }; collectionActions.handleChange(this.props, { diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js index e976519dfe635..ab234be28abea 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js @@ -78,10 +78,6 @@ export const IndexPattern = ({ allowLevelofDetail, }) => { const config = getUISettings(); - - const handleSelectChange = createSelectHandler(onChange); - const handleTextChange = createTextHandler(onChange); - const timeFieldName = `${prefix}time_field`; const indexPatternName = `${prefix}index_pattern`; const intervalName = `${prefix}interval`; @@ -100,6 +96,9 @@ export const IndexPattern = ({ [onChange, maxBarsName] ); + const handleSelectChange = createSelectHandler(onChange); + const handleTextChange = createTextHandler(onChange); + const timeRangeOptions = [ { label: i18n.translate('visTypeTimeseries.indexPattern.timeRange.lastValue', { @@ -119,7 +118,7 @@ export const IndexPattern = ({ const defaults = { default_index_pattern: '', - [indexPatternName]: '*', + [indexPatternName]: '', [intervalName]: AUTO_INTERVAL, [dropBucketName]: 1, [maxBarsName]: config.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), @@ -191,7 +190,7 @@ export const IndexPattern = ({ data-test-subj="metricsIndexPatternInput" disabled={disabled} placeholder={model.default_index_pattern} - onChange={handleTextChange(indexPatternName, '*')} + onChange={handleTextChange(indexPatternName)} value={model[indexPatternName]} /> @@ -204,7 +203,6 @@ export const IndexPattern = ({ })} > { - let handleChange; - let changeHandler; +describe('createSelectHandler', () => { + describe('createSelectHandler()', () => { + let handleChange: HandleChange; + let changeHandler: ReturnType; - beforeEach(() => { - handleChange = jest.fn(); - changeHandler = createSelectHandler(handleChange); - const fn = changeHandler('test'); - fn([{ value: 'foo' }]); - }); + beforeEach(() => { + handleChange = jest.fn(); + changeHandler = createSelectHandler(handleChange); + }); + + test('should calls handleChange() function with the correct data', () => { + const fn = changeHandler('test'); + + fn([{ value: 'foo', label: 'foo' }]); - test('calls handleChange() function with partial', () => { - expect(handleChange.mock.calls.length).toEqual(1); - expect(handleChange.mock.calls[0][0]).toEqual({ - test: 'foo', + expect(handleChange).toHaveBeenCalledWith({ + test: 'foo', + }); }); }); }); diff --git a/src/plugins/vis_type_timeseries/common/model_options.test.js b/src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.ts similarity index 71% rename from src/plugins/vis_type_timeseries/common/model_options.test.js rename to src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.ts index 7d01226bdc040..15f4e19702a7f 100644 --- a/src/plugins/vis_type_timeseries/common/model_options.test.js +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/create_select_handler.ts @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ +import { EuiComboBoxOptionOption } from '@elastic/eui'; -import { MODEL_TYPES } from './model_options'; +export type HandleChange = (partialModel: Record) => void; -describe('src/legacy/core_plugins/metrics/common/model_options.js', () => { - describe('MODEL_TYPES', () => { - test('should match a snapshot of constants', () => { - expect(MODEL_TYPES).toMatchSnapshot(); - }); +export const createSelectHandler = (handleChange: HandleChange) => (name: string) => ( + selected: EuiComboBoxOptionOption[] = [] +) => + handleChange?.({ + [name]: selected[0]?.value ?? null, }); -}); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/series_change_handler.js b/src/plugins/vis_type_timeseries/public/application/components/lib/series_change_handler.js index b6b99d7782762..854d9bf5c59bc 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/series_change_handler.js +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/series_change_handler.js @@ -17,7 +17,6 @@ * under the License. */ -import _ from 'lodash'; import { newMetricAggFn } from './new_metric_agg_fn'; import { isBasicAgg } from '../../../../common/agg_lookup'; import { handleAdd, handleChange } from './collection_actions'; @@ -30,8 +29,10 @@ export const seriesChangeHandler = (props, items) => (doc) => { handleAdd.call(null, props, () => { const metric = newMetricAggFn(); metric.type = doc.type; - const incompatPipelines = ['calculation', 'series_agg']; - if (!_.includes(incompatPipelines, doc.type)) metric.field = doc.id; + + if (!['calculation', 'series_agg'].includes(doc.type)) { + metric.field = doc.id; + } return metric; }); } else { diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js index ef7aec61a2f0d..9a59c3ece5849 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js @@ -46,7 +46,7 @@ const lessC = less(window, { env: 'production' }); import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { VisDataContext } from './../../contexts/vis_data_context'; +import { VisDataContext } from '../../contexts/vis_data_context'; class MarkdownPanelConfigUi extends Component { constructor(props) { diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index b2ea90d6a87fe..16bc4b0631396 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -45,7 +45,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -import { VisDataContext } from './../../contexts/vis_data_context'; +import { VisDataContext } from '../../contexts/vis_data_context'; import { BUCKET_TYPES } from '../../../../common/metric_types'; export class TablePanelConfig extends Component { static contextType = VisDataContext; diff --git a/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap b/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap index daff68e40dbae..09cd6d550fd96 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap +++ b/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap @@ -43,7 +43,7 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js } labelType="label" > - - { this.setState({ @@ -191,6 +189,31 @@ export class VisEditor extends Component { } componentDidMount() { + const dataStart = getDataStart(); + + dataStart.indexPatterns.getDefault().then(async (index) => { + const defaultIndexTitle = index?.title ?? ''; + const indexPatterns = extractIndexPatterns(this.props.visParams, defaultIndexTitle); + + this.setState({ + model: { + ...this.props.visParams, + /** @legacy + * please use IndexPatterns service instead + * **/ + default_index_pattern: defaultIndexTitle, + /** @legacy + * please use IndexPatterns service instead + * **/ + default_timefield: index?.timeFieldName ?? '', + }, + dirty: false, + autoApply: true, + visFields: await fetchFields(indexPatterns), + extractedIndexPatterns: [''], + }); + }); + this.props.eventEmitter.on('updateEditor', this.updateModel); } @@ -207,10 +230,8 @@ VisEditor.defaultProps = { VisEditor.propTypes = { vis: PropTypes.object, visData: PropTypes.object, - visFields: PropTypes.object, renderComplete: PropTypes.func, config: PropTypes.object, - savedObj: PropTypes.object, timeRange: PropTypes.object, appState: PropTypes.object, }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/vis.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/vis.js index a31be694cd172..46f266f631911 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/vis.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/vis.js @@ -22,7 +22,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { RedirectAppLinks } from '../../../../../../kibana_react/public'; import { createTickFormatter } from '../../lib/tick_formatter'; -import { calculateLabel } from '../../../../../common/calculate_label'; import { isSortable } from './is_sortable'; import { EuiToolTip, EuiIcon } from '@elastic/eui'; import { replaceVars } from '../../lib/replace_vars'; @@ -30,8 +29,6 @@ import { fieldFormats } from '../../../../../../../plugins/data/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { getFieldFormats, getCoreStart } from '../../../../services'; -import { METRIC_TYPES } from '../../../../../common/metric_types'; - function getColor(rules, colorKey, value) { let color; if (rules) { @@ -109,30 +106,19 @@ class TableVis extends Component { }; renderHeader() { - const { model, uiState, onUiState } = this.props; + const { model, uiState, onUiState, visData } = this.props; const stateKey = `${model.type}.sort`; const sort = uiState.get(stateKey, { column: '_default_', order: 'asc', }); - const calculateHeaderLabel = (metric, item) => { - const defaultLabel = item.label || calculateLabel(metric, item.metrics); - - switch (metric.type) { - case METRIC_TYPES.PERCENTILE: - return `${defaultLabel} (${last(metric.percentiles).value || 0})`; - case METRIC_TYPES.PERCENTILE_RANK: - return `${defaultLabel} (${last(metric.values) || 0})`; - default: - return defaultLabel; - } - }; + const calculateHeaderLabel = (metric, item) => + item.label || visData.series[0]?.series?.find((s) => item.id === s.id)?.label; const columns = this.visibleSeries.map((item) => { const metric = last(item.metrics); const label = calculateHeaderLabel(metric, item); - const handleClick = () => { if (!isSortable(metric)) return; let order; @@ -179,7 +165,7 @@ class TableVis extends Component { ); }); - const label = model.pivot_label || model.pivot_field || model.pivot_id; + const label = visData.pivot_label || model.pivot_label || model.pivot_id; let sortIcon; if (sort.column === '_default_') { sortIcon = sort.order === 'asc' ? 'sortUp' : 'sortDown'; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_with_splits.js b/src/plugins/vis_type_timeseries/public/application/components/vis_with_splits.js index 27891cdbb3943..8438b6899e835 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_with_splits.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_with_splits.js @@ -20,8 +20,7 @@ import React from 'react'; import { getDisplayName } from './lib/get_display_name'; import { labelDateFormatter } from './lib/label_date_formatter'; -import { last, findIndex, first } from 'lodash'; -import { calculateLabel } from '../../../common/calculate_label'; +import { findIndex, first } from 'lodash'; export function visWithSplits(WrappedComponent) { function SplitVisComponent(props) { @@ -35,8 +34,8 @@ export function visWithSplits(WrappedComponent) { const [seriesId, splitId] = series.id.split(':'); const seriesModel = model.series.find((s) => s.id === seriesId); if (!seriesModel || !splitId) return acc; - const metric = last(seriesModel.metrics); - const label = calculateLabel(metric, seriesModel.metrics); + + const label = series.splitByLabel; if (!acc[splitId]) { acc[splitId] = { @@ -102,6 +101,7 @@ export function visWithSplits(WrappedComponent) { return
    {rows}
    ; } + SplitVisComponent.displayName = `SplitVisComponent(${getDisplayName(WrappedComponent)})`; return SplitVisComponent; } diff --git a/src/plugins/vis_type_timeseries/public/application/editor_controller.js b/src/plugins/vis_type_timeseries/public/application/editor_controller.js index 548bf2623fc1a..953ebc4e5b75e 100644 --- a/src/plugins/vis_type_timeseries/public/application/editor_controller.js +++ b/src/plugins/vis_type_timeseries/public/application/editor_controller.js @@ -19,10 +19,11 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { fetchIndexPatternFields } from './lib/fetch_fields'; -import { getSavedObjectsClient, getUISettings, getI18n } from '../services'; +import { getUISettings, getI18n } from '../services'; import { VisEditor } from './components/vis_editor_lazy'; +export const TSVB_EDITOR_NAME = 'tsvbEditor'; + export class EditorController { constructor(el, vis, eventEmitter, embeddableHandler) { this.el = el; @@ -31,42 +32,18 @@ export class EditorController { this.eventEmitter = eventEmitter; this.state = { - fields: [], vis: vis, - isLoaded: false, }; } - fetchDefaultIndexPattern = async () => { - const indexPattern = await getSavedObjectsClient().client.get( - 'index-pattern', - getUISettings().get('defaultIndex') - ); - - return indexPattern.attributes; - }; - - fetchDefaultParams = async () => { - const { title, timeFieldName } = await this.fetchDefaultIndexPattern(); - - this.state.vis.params.default_index_pattern = title; - this.state.vis.params.default_timefield = timeFieldName; - this.state.fields = await fetchIndexPatternFields(this.state.vis); - - this.state.isLoaded = true; - }; - async render(params) { const I18nContext = getI18n().Context; - !this.state.isLoaded && (await this.fetchDefaultParams()); - render( {}} diff --git a/src/plugins/vis_type_timeseries/public/application/index.ts b/src/plugins/vis_type_timeseries/public/application/index.ts index 5e70169c4e483..feecedb78e095 100644 --- a/src/plugins/vis_type_timeseries/public/application/index.ts +++ b/src/plugins/vis_type_timeseries/public/application/index.ts @@ -18,5 +18,5 @@ */ // @ts-ignore -export { EditorController } from './editor_controller'; +export { EditorController, TSVB_EDITOR_NAME } from './editor_controller'; export * from './lib'; diff --git a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.js b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts similarity index 64% rename from src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.js rename to src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts index a32ab71f36357..ae78178af957e 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.js +++ b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts @@ -17,31 +17,43 @@ * under the License. */ import { i18n } from '@kbn/i18n'; -import { extractIndexPatterns } from '../../../common/extract_index_patterns'; -import { getCoreStart } from '../../services'; +import { getCoreStart, getDataStart } from '../../services'; import { ROUTES } from '../../../common/constants'; +import { SanitizedFieldType } from '../../../common/types'; + +export async function fetchFields( + indexes: string[] = [], + signal?: AbortSignal +): Promise> { + const patterns = Array.isArray(indexes) ? indexes : [indexes]; + const coreStart = getCoreStart(); + const dataStart = getDataStart(); -export async function fetchFields(indexPatterns = [], signal) { - const patterns = Array.isArray(indexPatterns) ? indexPatterns : [indexPatterns]; try { + const defaultIndexPattern = await dataStart.indexPatterns.getDefault(); const indexFields = await Promise.all( - patterns.map((pattern) => - getCoreStart().http.get(ROUTES.FIELDS, { + patterns.map(async (pattern) => { + return coreStart.http.get(ROUTES.FIELDS, { query: { index: pattern, }, signal, - }) - ) + }); + }) ); - return patterns.reduce( + const fields: Record = patterns.reduce( (cumulatedFields, currentPattern, index) => ({ ...cumulatedFields, [currentPattern]: indexFields[index], }), {} ); + + if (defaultIndexPattern?.title && patterns.includes(defaultIndexPattern.title)) { + fields[''] = fields[defaultIndexPattern.title]; + } + return fields; } catch (error) { if (error.name !== 'AbortError') { getCoreStart().notifications.toasts.addDanger({ @@ -52,11 +64,5 @@ export async function fetchFields(indexPatterns = [], signal) { }); } } - return []; -} - -export async function fetchIndexPatternFields({ params, fields = {} }) { - const indexPatterns = extractIndexPatterns(params, fields); - - return await fetchFields(indexPatterns); + return {}; } diff --git a/src/plugins/vis_type_timeseries/public/metrics_fn.ts b/src/plugins/vis_type_timeseries/public/metrics_fn.ts index 60acd35b22402..825b964270794 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_fn.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_fn.ts @@ -65,7 +65,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ help: '', }, }, - async fn(input, args) { + async fn(input, args, { getSearchSessionId }) { const visParams: TimeseriesVisParams = JSON.parse(args.params); const uiState = JSON.parse(args.uiState); @@ -73,6 +73,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ input, visParams, uiState, + searchSessionId: getSearchSessionId(), }); return { diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index 41dc26c8c130d..9a3df612e7391 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; -import { EditorController } from './application'; +import { TSVB_EDITOR_NAME } from './application'; import { PANEL_TYPES } from '../common/panel_types'; import { toExpressionAst } from './to_ast'; import { VIS_EVENT_TO_TRIGGER, VisGroups, VisParams } from '../../visualizations/public'; @@ -70,7 +70,9 @@ export const metricsVisDefinition = { tooltip_mode: 'show_all', }, }, - editor: EditorController, + editorConfig: { + editor: TSVB_EDITOR_NAME, + }, options: { showQueryBar: false, showFilterBar: false, diff --git a/src/plugins/vis_type_timeseries/public/plugin.ts b/src/plugins/vis_type_timeseries/public/plugin.ts index d36b3611680af..a7f8d0ec61a03 100644 --- a/src/plugins/vis_type_timeseries/public/plugin.ts +++ b/src/plugins/vis_type_timeseries/public/plugin.ts @@ -22,6 +22,8 @@ import './application/index.scss'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizePluginSetup } from '../../visualize/public'; +import { EditorController, TSVB_EDITOR_NAME } from './application'; import { createMetricsFn } from './metrics_fn'; import { metricsVisDefinition } from './metrics_type'; @@ -43,6 +45,7 @@ export interface MetricsPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; charts: ChartsPluginSetup; + visualize: VisualizePluginSetup; } /** @internal */ @@ -60,8 +63,9 @@ export class MetricsPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, charts }: MetricsPluginSetupDependencies + { expressions, visualizations, charts, visualize }: MetricsPluginSetupDependencies ) { + visualize.visEditorsRegistry.register(TSVB_EDITOR_NAME, EditorController); expressions.registerFunction(createMetricsFn); expressions.registerRenderer( getTimeseriesVisRenderer({ diff --git a/src/plugins/vis_type_timeseries/public/request_handler.ts b/src/plugins/vis_type_timeseries/public/request_handler.ts index aa45453515277..16b5e4c2dc4fa 100644 --- a/src/plugins/vis_type_timeseries/public/request_handler.ts +++ b/src/plugins/vis_type_timeseries/public/request_handler.ts @@ -29,39 +29,57 @@ interface MetricsRequestHandlerParams { input: KibanaContext | null; uiState: Record; visParams: TimeseriesVisParams; + searchSessionId?: string; } export const metricsRequestHandler = async ({ input, uiState, visParams, + searchSessionId, }: MetricsRequestHandlerParams): Promise => { const config = getUISettings(); const timezone = getTimezone(config); const uiStateObj = uiState[visParams.type] ?? {}; - const dataSearch = getDataStart(); - const parsedTimeRange = dataSearch.query.timefilter.timefilter.calculateBounds(input?.timeRange!); + const data = getDataStart(); + const dataSearch = getDataStart().search; + const parsedTimeRange = data.query.timefilter.timefilter.calculateBounds(input?.timeRange!); if (visParams && visParams.id && !visParams.isModelInvalid) { const maxBuckets = config.get(MAX_BUCKETS_SETTING); validateInterval(parsedTimeRange, visParams, maxBuckets); - const resp = await getCoreStart().http.post(ROUTES.VIS_DATA, { - body: JSON.stringify({ - timerange: { - timezone, - ...parsedTimeRange, + const untrackSearch = + dataSearch.session.isCurrentSession(searchSessionId) && + dataSearch.session.trackSearch({ + abort: () => { + // TODO: support search cancellations }, - query: input?.query, - filters: input?.filters, - panels: [visParams], - state: uiStateObj, - sessionId: dataSearch.search.session.getSessionId(), - }), - }); + }); - return resp; + try { + return await getCoreStart().http.post(ROUTES.VIS_DATA, { + body: JSON.stringify({ + timerange: { + timezone, + ...parsedTimeRange, + }, + query: input?.query, + filters: input?.filters, + panels: [visParams], + state: uiStateObj, + ...(searchSessionId && { + searchSession: dataSearch.session.getSearchOptions(searchSessionId), + }), + }), + }); + } finally { + if (untrackSearch && dataSearch.session.isCurrentSession(searchSessionId)) { + // untrack if this search still belongs to current session + untrackSearch(); + } + } } return {}; diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index 8f87318222f2b..d15332b26701c 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -16,24 +16,31 @@ * specific language governing permissions and limitations * under the License. */ -import { uniqBy, get } from 'lodash'; +import { uniqBy } from 'lodash'; import { first, map } from 'rxjs/operators'; import { KibanaRequest, RequestHandlerContext } from 'kibana/server'; import { Framework } from '../plugin'; -import { - indexPatterns, - IndexPatternFieldDescriptor, - IndexPatternsFetcher, -} from '../../../data/server'; +import { IndexPatternsFetcher } from '../../../data/server'; import { ReqFacade } from './search_strategies/strategies/abstract_search_strategy'; export async function getFields( requestContext: RequestHandlerContext, request: KibanaRequest, framework: Framework, - indexPattern: string + indexPatternString: string ) { + const getIndexPatternsService = async () => { + const [, { data }] = await framework.core.getStartServices(); + + return await data.indexPatterns.indexPatternsServiceFactory( + requestContext.core.savedObjects.client, + requestContext.core.elasticsearch.client.asCurrentUser + ); + }; + + const indexPatternsService = await getIndexPatternsService(); + // NOTE / TODO: This facade has been put in place to make migrating to the New Platform easier. It // removes the need to refactor many layers of dependencies on "req", and instead just augments the top // level object passed from here. The layers should be refactored fully at some point, but for now @@ -44,7 +51,7 @@ export async function getFields( framework, payload: {}, pre: { - indexPatternsService: new IndexPatternsFetcher( + indexPatternsFetcher: new IndexPatternsFetcher( requestContext.core.elasticsearch.client.asCurrentUser ), }, @@ -58,19 +65,13 @@ export async function getFields( ) .toPromise(); }, + getIndexPatternsService: async () => indexPatternsService, }; - let indexPatternString = indexPattern; if (!indexPatternString) { - const [{ savedObjects, elasticsearch }, { data }] = await framework.core.getStartServices(); - const savedObjectsClient = savedObjects.getScopedClient(request); - const clusterClient = elasticsearch.client.asScoped(request).asCurrentUser; - const indexPatternsService = await data.indexPatterns.indexPatternsServiceFactory( - savedObjectsClient, - clusterClient - ); const defaultIndexPattern = await indexPatternsService.getDefault(); - indexPatternString = get(defaultIndexPattern, 'title', ''); + + indexPatternString = defaultIndexPattern?.title ?? ''; } const { @@ -78,12 +79,10 @@ export async function getFields( capabilities, } = (await framework.searchStrategyRegistry.getViableStrategy(reqFacade, indexPatternString))!; - const fields = ((await searchStrategy.getFieldsForWildcard( + const fields = await searchStrategy.getFieldsForWildcard( reqFacade, indexPatternString, capabilities - )) as IndexPatternFieldDescriptor[]).filter( - (field) => field.aggregatable && !indexPatterns.isNestedField(field) ); return uniqBy(fields, (field) => field.name); diff --git a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts index aefbe0ea78d4b..d450bb205c9ce 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts @@ -71,6 +71,14 @@ export function getVisData( ) .toPromise(); }, + getIndexPatternsService: async () => { + const [, { data }] = await framework.core.getStartServices(); + + return await data.indexPatterns.indexPatternsServiceFactory( + requestContext.core.savedObjects.client, + requestContext.core.elasticsearch.client.asCurrentUser + ); + }, }; const promises = reqFacade.payload.panels.map(getPanelData(reqFacade)); return Promise.all(promises).then((res) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index 6fbed1ddfba0f..afe598393ab92 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -24,7 +24,8 @@ import { DefaultSearchStrategy } from './strategies/default_search_strategy'; import { extractIndexPatterns } from '../../../common/extract_index_patterns'; export type RequestFacade = any; -export type Panel = any; + +import { PanelSchema } from '../../../common/types'; export class SearchStrategyRegistry { private strategies: AbstractSearchStrategy[] = []; @@ -53,8 +54,8 @@ export class SearchStrategyRegistry { } } - async getViableStrategyForPanel(req: RequestFacade, panel: Panel) { - const indexPattern = extractIndexPatterns(panel).join(','); + async getViableStrategyForPanel(req: RequestFacade, panel: PanelSchema) { + const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern).join(','); return this.getViableStrategy(req, indexPattern); } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js index 2c38e883cd69f..704f865bf7f6e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js @@ -26,14 +26,17 @@ describe('AbstractSearchStrategy', () => { let indexPattern; beforeEach(() => { - mockedFields = {}; + mockedFields = []; req = { payload: {}, pre: { - indexPatternsService: { + indexPatternsFetcher: { getFieldsForWildcard: jest.fn().mockReturnValue(mockedFields), }, }, + getIndexPatternsService: jest.fn(() => ({ + find: jest.fn(() => []), + })), }; abstractSearchStrategy = new AbstractSearchStrategy(); @@ -48,9 +51,10 @@ describe('AbstractSearchStrategy', () => { test('should return fields for wildcard', async () => { const fields = await abstractSearchStrategy.getFieldsForWildcard(req, indexPattern); - expect(fields).toBe(mockedFields); - expect(req.pre.indexPatternsService.getFieldsForWildcard).toHaveBeenCalledWith({ + expect(fields).toEqual(mockedFields); + expect(req.pre.indexPatternsFetcher.getFieldsForWildcard).toHaveBeenCalledWith({ pattern: indexPattern, + metaFields: [], fieldCapsOptions: { allow_no_indices: true }, }); }); @@ -62,7 +66,11 @@ describe('AbstractSearchStrategy', () => { const responses = await abstractSearchStrategy.search( { payload: { - sessionId: 1, + searchSession: { + sessionId: '1', + isRestore: false, + isStored: true, + }, }, requestContext: { search: { search: searchFn }, @@ -81,7 +89,9 @@ describe('AbstractSearchStrategy', () => { indexType: undefined, }, { - sessionId: 1, + sessionId: '1', + isRestore: false, + isStored: true, } ); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index 71461d319f2b6..77da99fb29330 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -17,16 +17,19 @@ * under the License. */ -import { +import type { RequestHandlerContext, FakeRequest, IUiSettingsClient, SavedObjectsClientContract, } from 'kibana/server'; -import { Framework } from '../../../plugin'; -import { IndexPatternsFetcher } from '../../../../../data/server'; -import { VisPayload } from '../../../../common/types'; +import type { Framework } from '../../../plugin'; +import type { IndexPatternsFetcher, IFieldType } from '../../../../../data/server'; +import type { VisPayload } from '../../../../common/types'; +import type { IndexPatternsService } from '../../../../../data/common'; +import { indexPatterns } from '../../../../../data/server'; +import { SanitizedFieldType } from '../../../../common/types'; /** * ReqFacade is a regular KibanaRequest object extended with additional service @@ -39,17 +42,30 @@ export interface ReqFacade extends FakeRequest { framework: Framework; payload: T; pre: { - indexPatternsService?: IndexPatternsFetcher; + indexPatternsFetcher?: IndexPatternsFetcher; }; getUiSettingsService: () => IUiSettingsClient; getSavedObjectsClient: () => SavedObjectsClientContract; getEsShardTimeout: () => Promise; + getIndexPatternsService: () => Promise; } +const toSanitizedFieldType = (fields: IFieldType[]) => { + return fields + .filter((field) => field.aggregatable && !indexPatterns.isNestedField(field)) + .map( + (field: IFieldType) => + ({ + name: field.name, + label: field.customLabel ?? field.name, + type: field.type, + } as SanitizedFieldType) + ); +}; + export abstract class AbstractSearchStrategy { async search(req: ReqFacade, bodies: any[], indexType?: string) { const requests: any[] = []; - const { sessionId } = req.payload; bodies.forEach((body) => { requests.push( @@ -61,9 +77,7 @@ export abstract class AbstractSearchStrategy { ...body, }, }, - { - sessionId, - } + req.payload.searchSession ) .toPromise() ); @@ -81,13 +95,27 @@ export abstract class AbstractSearchStrategy { async getFieldsForWildcard( req: ReqFacade, indexPattern: string, - capabilities?: unknown + capabilities?: unknown, + options?: Partial<{ + type: string; + rollupIndex: string; + }> ) { - const { indexPatternsService } = req.pre; + const { indexPatternsFetcher } = req.pre; + const indexPatternsService = await req.getIndexPatternsService(); + const kibanaIndexPattern = (await indexPatternsService.find(indexPattern)).find( + (index) => index.title === indexPattern + ); - return await indexPatternsService!.getFieldsForWildcard({ - pattern: indexPattern, - fieldCapsOptions: { allow_no_indices: true }, - }); + return toSanitizedFieldType( + kibanaIndexPattern + ? kibanaIndexPattern.fields.getAll() + : await indexPatternsFetcher!.getFieldsForWildcard({ + pattern: indexPattern, + fieldCapsOptions: { allow_no_indices: true }, + metaFields: [], + ...options, + }) + ); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index e1f519456d373..0744b50c27ca2 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -30,4 +30,12 @@ export class DefaultSearchStrategy extends AbstractSearchStrategy { capabilities: new DefaultSearchCapabilities(req), }); } + + async getFieldsForWildcard( + req: ReqFacade, + indexPattern: string, + capabilities?: unknown + ) { + return super.getFieldsForWildcard(req, indexPattern, capabilities); + } } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/build_request_body.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/build_request_body.js index 9ea62e2700517..1e93967bdde9e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/build_request_body.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/build_request_body.js @@ -32,8 +32,8 @@ import { processors } from '../request_processors/annotations'; * ] * @returns {Object} doc - processed body */ -export function buildAnnotationRequest(...args) { +export async function buildAnnotationRequest(...args) { const processor = buildProcessorFunction(processors, ...args); - const doc = processor({}); + const doc = await processor({}); return doc; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.js index 1b2334c7dea94..16099ccd6dba4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.js @@ -19,7 +19,6 @@ import { buildAnnotationRequest } from './build_request_body'; import { getEsShardTimeout } from '../helpers/get_es_shard_timeout'; import { getIndexPatternObject } from '../helpers/get_index_pattern'; -import { UI_SETTINGS } from '../../../../../data/common'; export async function getAnnotationRequestParams( req, @@ -32,17 +31,14 @@ export async function getAnnotationRequestParams( const esShardTimeout = await getEsShardTimeout(req); const indexPattern = annotation.index_pattern; const { indexPatternObject, indexPatternString } = await getIndexPatternObject(req, indexPattern); - const request = buildAnnotationRequest( + const request = await buildAnnotationRequest( req, panel, annotation, esQueryConfig, indexPatternObject, capabilities, - { - maxBarsUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), - barTargetUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), - } + uiSettings ); return { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.js index 232efc7514a5a..f699a50db66af 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.js @@ -45,11 +45,14 @@ export async function getSeriesData(req, panel) { ); const data = await searchStrategy.search(req, searches); - const handleResponseBodyFn = handleResponseBody(panel); + const handleResponseBodyFn = handleResponseBody(panel, req, searchStrategy, capabilities); - const series = data.map((resp) => - handleResponseBodyFn(resp.rawResponse ? resp.rawResponse : resp) + const series = await Promise.all( + data.map( + async (resp) => await handleResponseBodyFn(resp.rawResponse ? resp.rawResponse : resp) + ) ); + let annotations = null; if (panel.annotations && panel.annotations.length) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js index eaaa5a9605b4b..a7b304e5e5866 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js @@ -16,13 +16,15 @@ * specific language governing permissions and limitations * under the License. */ + import { buildRequestBody } from './table/build_request_body'; import { handleErrorResponse } from './handle_error_response'; import { get } from 'lodash'; import { processBucket } from './table/process_bucket'; import { getEsQueryConfig } from './helpers/get_es_query_uisettings'; import { getIndexPatternObject } from './helpers/get_index_pattern'; -import { UI_SETTINGS } from '../../../../data/common'; +import { createFieldsFetcher } from './helpers/fields_fetcher'; +import { extractFieldLabel } from '../../../common/calculate_label'; export async function getTableData(req, panel) { const panelIndexPattern = panel.index_pattern; @@ -33,18 +35,33 @@ export async function getTableData(req, panel) { } = await req.framework.searchStrategyRegistry.getViableStrategy(req, panelIndexPattern); const esQueryConfig = await getEsQueryConfig(req); const { indexPatternObject } = await getIndexPatternObject(req, panelIndexPattern); + const extractFields = createFieldsFetcher(req, searchStrategy, capabilities); + + const calculatePivotLabel = async () => { + if (panel.pivot_id && indexPatternObject?.title) { + const fields = await extractFields(indexPatternObject.title); + + return extractFieldLabel(fields, panel.pivot_id); + } + return panel.pivot_id; + }; const meta = { type: panel.type, + pivot_label: panel.pivot_label || (await calculatePivotLabel()), uiRestrictions: capabilities.uiRestrictions, }; try { const uiSettings = req.getUiSettingsService(); - const body = buildRequestBody(req, panel, esQueryConfig, indexPatternObject, capabilities, { - maxBarsUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), - barTargetUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), - }); + const body = await buildRequestBody( + req, + panel, + esQueryConfig, + indexPatternObject, + capabilities, + uiSettings + ); const [resp] = await searchStrategy.search(req, [ { @@ -59,9 +76,13 @@ export async function getTableData(req, panel) { [] ); + const series = await Promise.all( + buckets.map(processBucket(panel, req, searchStrategy, capabilities, extractFields)) + ); + return { ...meta, - series: buckets.map(processBucket(panel)), + series, }; } catch (err) { if (err.body || err.name === 'KQLSyntaxError') { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.js index dc2936072165e..431b5fb83d831 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.js @@ -128,7 +128,8 @@ export const bucketTransform = { }, }; if (bucket.order_by) { - set(body, 'aggs.docs.top_hits.sort', [{ [bucket.order_by]: { order: bucket.order } }]); + const orderField = bucket.order_by; + set(body, 'aggs.docs.top_hits.sort', [{ [orderField]: { order: bucket.order } }]); } return body; }, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts new file mode 100644 index 0000000000000..6ee90eabf9f02 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AbstractSearchStrategy, DefaultSearchCapabilities, ReqFacade } from '../../..'; + +export const createFieldsFetcher = ( + req: ReqFacade, + searchStrategy: AbstractSearchStrategy, + capabilities: DefaultSearchCapabilities +) => { + const fieldsCacheMap = new Map(); + + return async (index: string) => { + if (fieldsCacheMap.has(index)) { + return fieldsCacheMap.get(index); + } + + const fields = await searchStrategy.getFieldsForWildcard(req, index, capabilities); + + fieldsCacheMap.set(index, fields); + + return fields; + }; +}; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.js index 6c162e327fb21..e491a6795ba5d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.js @@ -27,7 +27,7 @@ import { formatKey } from './format_key'; const getTimeSeries = (resp, series) => _.get(resp, `aggregations.timeseries`) || _.get(resp, `aggregations.${series.id}.timeseries`); -export function getSplits(resp, panel, series, meta) { +export async function getSplits(resp, panel, series, meta, extractFields) { if (!meta) { meta = _.get(resp, `aggregations.${series.id}.meta`); } @@ -35,12 +35,17 @@ export function getSplits(resp, panel, series, meta) { const color = new Color(series.color); const metric = getLastMetric(series); const buckets = _.get(resp, `aggregations.${series.id}.buckets`); + + const fieldsForMetaIndex = meta.index ? await extractFields(meta.index) : []; + const splitByLabel = calculateLabel(metric, series.metrics, fieldsForMetaIndex); + if (buckets) { if (Array.isArray(buckets)) { const size = buckets.length; const colors = getSplitColors(series.color, size, series.split_color_mode); return buckets.map((bucket) => { bucket.id = `${series.id}:${bucket.key}`; + bucket.splitByLabel = splitByLabel; bucket.label = formatKey(bucket.key, series); bucket.labelFormatted = bucket.key_as_string ? formatKey(bucket.key_as_string, series) : ''; bucket.color = panel.type === 'top_n' ? color.string() : colors.shift(); @@ -72,10 +77,12 @@ export function getSplits(resp, panel, series, meta) { .forEach((m) => { mergeObj[m.id] = _.get(resp, `aggregations.${series.id}.${m.id}`); }); + return [ { id: series.id, - label: series.label || calculateLabel(metric, series.metrics), + splitByLabel, + label: series.label || splitByLabel, color: color.string(), ...mergeObj, meta, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js index 5ccd61a1c9102..dac269ed2f6c3 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js @@ -20,7 +20,7 @@ import { getSplits } from './get_splits'; describe('getSplits(resp, panel, series)', () => { - test('should return a splits for everything/filter group bys', () => { + test('should return a splits for everything/filter group bys', async () => { const resp = { aggregations: { SERIES: { @@ -40,19 +40,20 @@ describe('getSplits(resp, panel, series)', () => { { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, ], }; - expect(getSplits(resp, panel, series)).toEqual([ + expect(await getSplits(resp, panel, series, undefined)).toEqual([ { id: 'SERIES', label: 'Overall Average of Average of cpu', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 1 }, }, ]); }); - test('should return a splits for terms group bys for top_n', () => { + test('should return a splits for terms group bys for top_n', async () => { const resp = { aggregations: { SERIES: { @@ -84,7 +85,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'top_n' }; - expect(getSplits(resp, panel, series)).toEqual([ + expect(await getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -92,6 +93,7 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 1 }, }, @@ -102,13 +104,14 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 2 }, }, ]); }); - test('should return a splits for terms group with label formatted by {{key}} placeholder', () => { + test('should return a splits for terms group with label formatted by {{key}} placeholder', async () => { const resp = { aggregations: { SERIES: { @@ -141,7 +144,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'top_n' }; - expect(getSplits(resp, panel, series)).toEqual([ + expect(await getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -149,6 +152,7 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 1 }, }, @@ -159,13 +163,14 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 2 }, }, ]); }); - test('should return a splits for terms group with labelFormatted if {{key}} placeholder is applied and key_as_string exists', () => { + test('should return a splits for terms group with labelFormatted if {{key}} placeholder is applied and key_as_string exists', async () => { const resp = { aggregations: { SERIES: { @@ -200,7 +205,8 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'top_n' }; - expect(getSplits(resp, panel, series)).toEqual([ + + expect(await getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -209,6 +215,7 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '--false--', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 1 }, }, @@ -220,6 +227,7 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '--true--', meta: { bucketSize: 10 }, color: 'rgb(255, 0, 0)', + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 2 }, }, @@ -247,7 +255,7 @@ describe('getSplits(resp, panel, series)', () => { }, }; - test('should return a splits with no color', () => { + test('should return a splits with no color', async () => { const series = { id: 'SERIES', color: '#F00', @@ -260,7 +268,8 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).toEqual([ + + expect(await getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -268,6 +277,7 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: undefined, + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 1 }, }, @@ -278,13 +288,14 @@ describe('getSplits(resp, panel, series)', () => { labelFormatted: '', meta: { bucketSize: 10 }, color: undefined, + splitByLabel: 'Overall Average of Average of cpu', timeseries: { buckets: [] }, SIBAGG: { value: 2 }, }, ]); }); - test('should return gradient color', () => { + test('should return gradient color', async () => { const series = { id: 'SERIES', color: '#F00', @@ -298,7 +309,8 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).toEqual([ + + expect(await getSplits(resp, panel, series)).toEqual([ expect.objectContaining({ color: 'rgb(255, 0, 0)', }), @@ -308,7 +320,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - test('should return rainbow color', () => { + test('should return rainbow color', async () => { const series = { id: 'SERIES', color: '#F00', @@ -322,7 +334,8 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).toEqual([ + + expect(await getSplits(resp, panel, series)).toEqual([ expect.objectContaining({ color: '#68BC00', }), @@ -333,7 +346,7 @@ describe('getSplits(resp, panel, series)', () => { }); }); - test('should return a splits for filters group bys', () => { + test('should return a splits for filters group bys', async () => { const resp = { aggregations: { SERIES: { @@ -360,7 +373,8 @@ describe('getSplits(resp, panel, series)', () => { metrics: [{ id: 'COUNT', type: 'count' }], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).toEqual([ + + expect(await getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:filter-1', key: 'filter-1', diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/unit_to_seconds.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/unit_to_seconds.ts index 8950e05c85d4f..22dfc590245ac 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/unit_to_seconds.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/unit_to_seconds.ts @@ -37,7 +37,7 @@ const units: Record = { const sortedUnits = sortBy(Object.keys(units), (key: Unit) => units[key]); -interface ParsedInterval { +export interface ParsedInterval { value: number; unit: Unit; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js index 617a75f6bd59f..f32bacac82dac 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js @@ -20,7 +20,8 @@ import { overwrite } from '../../helpers'; import { getBucketSize } from '../../helpers/get_bucket_size'; import { getTimerange } from '../../helpers/get_timerange'; -import { search } from '../../../../../../../plugins/data/server'; +import { search, UI_SETTINGS } from '../../../../../../../plugins/data/server'; + const { dateHistogramInterval } = search.aggs; export function dateHistogram( @@ -30,9 +31,10 @@ export function dateHistogram( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const timeField = annotation.time_field; const { bucketSize, intervalString } = getBucketSize( req, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/query.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/query.js index cf02f601ea5ff..ec6f52ca30a9c 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/query.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/query.js @@ -19,7 +19,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { getTimerange } from '../../helpers/get_timerange'; -import { esQuery } from '../../../../../../data/server'; +import { esQuery, UI_SETTINGS } from '../../../../../../data/server'; export function query( req, @@ -28,9 +28,10 @@ export function query( esQueryConfig, indexPattern, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const timeField = annotation.time_field; const { bucketSize } = getBucketSize(req, 'auto', capabilities, barTargetUiSettings); const { from, to } = getTimerange(req); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/top_hits.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/top_hits.js index bdf2aac943b1b..2e1d9291d1c5f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/top_hits.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/top_hits.js @@ -23,6 +23,7 @@ export function topHits(req, panel, annotation) { return (next) => (doc) => { const fields = (annotation.fields && annotation.fields.split(/[,\s]+/)) || []; const timeField = annotation.time_field; + overwrite(doc, `aggs.${annotation.id}.aggs.hits.top_hits`, { sort: [ { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js index 98c683bda1fdb..2133d39913180 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js @@ -22,7 +22,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { offsetTime } from '../../offset_time'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { isLastValueTimerangeMode } from '../../helpers/get_timerange_mode'; -import { search } from '../../../../../../../plugins/data/server'; +import { search, UI_SETTINGS } from '../../../../../../../plugins/data/server'; const { dateHistogramInterval } = search.aggs; export function dateHistogram( @@ -32,9 +32,12 @@ export function dateHistogram( esQueryConfig, indexPatternObject, capabilities, - { maxBarsUiSettings, barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const maxBarsUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS); + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); + const { timeField, interval, maxBars } = getIntervalAndTimefield( panel, series, @@ -73,11 +76,10 @@ export function dateHistogram( ? getDateHistogramForLastBucketMode() : getDateHistogramForEntireTimerangeMode(); - // master - overwrite(doc, `aggs.${series.id}.meta`, { timeField, intervalString, + index: indexPatternObject?.title, bucketSize, seriesId: series.id, }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js index aa95a79a62796..05f2d5f39aa65 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js @@ -19,6 +19,7 @@ import { DefaultSearchCapabilities } from '../../../search_strategies/default_search_capabilities'; import { dateHistogram } from './date_histogram'; +import { UI_SETTINGS } from '../../../../../../data/common'; describe('dateHistogram(req, panel, series)', () => { let panel; @@ -51,20 +52,30 @@ describe('dateHistogram(req, panel, series)', () => { }; indexPatternObject = {}; capabilities = new DefaultSearchCapabilities(req); - uiSettings = { maxBarsUiSettings: 100, barTargetUiSettings: 50 }; + uiSettings = { + get: async (key) => (key === UI_SETTINGS.HISTOGRAM_MAX_BARS ? 100 : 50), + }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - dateHistogram(req, panel, series, config, indexPatternObject, capabilities, uiSettings)(next)( - {} - ); + + await dateHistogram( + req, + panel, + series, + config, + indexPatternObject, + capabilities, + uiSettings + )(next)({}); + expect(next.mock.calls.length).toEqual(1); }); - test('returns valid date histogram', () => { + test('returns valid date histogram', async () => { const next = (doc) => doc; - const doc = dateHistogram( + const doc = await dateHistogram( req, panel, series, @@ -102,10 +113,10 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - test('returns valid date histogram (offset by 1h)', () => { + test('returns valid date histogram (offset by 1h)', async () => { series.offset_time = '1h'; const next = (doc) => doc; - const doc = dateHistogram( + const doc = await dateHistogram( req, panel, series, @@ -143,13 +154,13 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - test('returns valid date histogram with overridden index pattern', () => { + test('returns valid date histogram with overridden index pattern', async () => { series.override_index_pattern = 1; series.series_index_pattern = '*'; series.series_time_field = 'timestamp'; series.series_interval = '20s'; const next = (doc) => doc; - const doc = dateHistogram( + const doc = await dateHistogram( req, panel, series, @@ -188,12 +199,12 @@ describe('dateHistogram(req, panel, series)', () => { }); describe('dateHistogram for entire time range mode', () => { - test('should ignore entire range mode for timeseries', () => { + test('should ignore entire range mode for timeseries', async () => { panel.time_range_mode = 'entire_time_range'; panel.type = 'timeseries'; const next = (doc) => doc; - const doc = dateHistogram( + const doc = await dateHistogram( req, panel, series, @@ -207,11 +218,11 @@ describe('dateHistogram(req, panel, series)', () => { expect(doc.aggs.test.aggs.timeseries.date_histogram).toBeDefined(); }); - test('should returns valid date histogram for entire range mode', () => { + test('should returns valid date histogram for entire range mode', async () => { panel.time_range_mode = 'entire_time_range'; const next = (doc) => doc; - const doc = dateHistogram( + const doc = await dateHistogram( req, panel, series, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js index 6c1699912f76f..9e05a7631a9f5 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js @@ -17,11 +17,12 @@ * under the License. */ -const filter = (metric) => metric.type === 'filter_ratio'; import { bucketTransform } from '../../helpers/bucket_transform'; import { overwrite } from '../../helpers'; import { esQuery } from '../../../../../../data/server'; +const filter = (metric) => metric.type === 'filter_ratio'; + export function ratios(req, panel, series, esQueryConfig, indexPatternObject) { return (next) => (doc) => { if (series.metrics.some(filter)) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js index 023ee054a5e13..7441ed0a274f2 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js @@ -20,6 +20,7 @@ import { overwrite } from '../../helpers'; import { getBucketSize } from '../../helpers/get_bucket_size'; import { bucketTransform } from '../../helpers/bucket_transform'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; +import { UI_SETTINGS } from '../../../../../../data/common'; export function metricBuckets( req, @@ -28,9 +29,11 @@ export function metricBuckets( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); + const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js index 2154d2257815b..1789517c0f332 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js @@ -63,20 +63,20 @@ describe('metricBuckets(req, panel, series)', () => { {}, undefined, { - barTargetUiSettings: 50, + get: async () => 50, } ); }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - metricBucketsProcessor(next)({}); + await metricBucketsProcessor(next)({}); expect(next.mock.calls.length).toEqual(1); }); - test('returns metric aggs', () => { + test('returns metric aggs', async () => { const next = (doc) => doc; - const doc = metricBucketsProcessor(next)({}); + const doc = await metricBucketsProcessor(next)({}); expect(doc).toEqual({ aggs: { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js index c16e0fd3aaf15..8e18ba725b003 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js @@ -21,6 +21,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { bucketTransform } from '../../helpers/bucket_transform'; import { overwrite } from '../../helpers'; +import { UI_SETTINGS } from '../../../../../../data/common'; export const filter = (metric) => metric.type === 'positive_rate'; @@ -29,7 +30,11 @@ export const createPositiveRate = (doc, intervalString, aggRoot) => (metric) => const derivativeFn = bucketTransform.derivative; const positiveOnlyFn = bucketTransform.positive_only; - const maxMetric = { id: `${metric.id}-positive-rate-max`, type: 'max', field: metric.field }; + const maxMetric = { + id: `${metric.id}-positive-rate-max`, + type: 'max', + field: metric.field, + }; const derivativeMetric = { id: `${metric.id}-positive-rate-derivative`, type: 'derivative', @@ -64,9 +69,11 @@ export function positiveRate( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); + const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js index d891fc01bb266..acec4b466f397 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js @@ -51,19 +51,21 @@ describe('positiveRate(req, panel, series)', () => { }, }; uiSettings = { - barTargetUiSettings: 50, + get: async () => 50, }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - positiveRate(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + await positiveRate(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + expect(next.mock.calls.length).toEqual(1); }); - test('returns positive rate aggs', () => { + test('returns positive rate aggs', async () => { const next = (doc) => doc; - const doc = positiveRate(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + const doc = await positiveRate(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + expect(doc).toEqual({ aggs: { test: { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js index f69473b613d1b..b17d63c10877a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js @@ -21,6 +21,7 @@ import { overwrite } from '../../helpers'; import { getBucketSize } from '../../helpers/get_bucket_size'; import { bucketTransform } from '../../helpers/bucket_transform'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; +import { UI_SETTINGS } from '../../../../../../data/common'; export function siblingBuckets( req, @@ -29,9 +30,10 @@ export function siblingBuckets( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); const { bucketSize } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js index 48714e83341ea..367b6fa242b72 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js @@ -56,19 +56,19 @@ describe('siblingBuckets(req, panel, series)', () => { }, }; uiSettings = { - barTargetUiSettings: 50, + get: async () => 50, }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - siblingBuckets(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + await siblingBuckets(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); expect(next.mock.calls.length).toEqual(1); }); - test('returns sibling aggs', () => { + test('returns sibling aggs', async () => { const next = (doc) => doc; - const doc = siblingBuckets(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); + const doc = await siblingBuckets(req, panel, series, {}, {}, undefined, uiSettings)(next)({}); expect(doc).toEqual({ aggs: { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js index 240a5d76b7c6a..6a8006f2f5fea 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.js @@ -25,9 +25,12 @@ import { bucketTransform } from '../../helpers/bucket_transform'; export function splitByTerms(req, panel, series) { return (next) => (doc) => { if (series.split_mode === 'terms' && series.terms_field) { + const termsField = series.terms_field; + const orderByTerms = series.terms_order_by; + const direction = series.terms_direction || 'desc'; - const metric = series.metrics.find((item) => item.id === series.terms_order_by); - overwrite(doc, `aggs.${series.id}.terms.field`, series.terms_field); + const metric = series.metrics.find((item) => item.id === orderByTerms); + overwrite(doc, `aggs.${series.id}.terms.field`, termsField); overwrite(doc, `aggs.${series.id}.terms.size`, series.terms_size); if (series.terms_include) { overwrite(doc, `aggs.${series.id}.terms.include`, series.terms_include); @@ -36,16 +39,16 @@ export function splitByTerms(req, panel, series) { overwrite(doc, `aggs.${series.id}.terms.exclude`, series.terms_exclude); } if (metric && metric.type !== 'count' && ~basicAggs.indexOf(metric.type)) { - const sortAggKey = `${series.terms_order_by}-SORT`; + const sortAggKey = `${orderByTerms}-SORT`; const fn = bucketTransform[metric.type]; - const bucketPath = getBucketsPath(series.terms_order_by, series.metrics).replace( - series.terms_order_by, + const bucketPath = getBucketsPath(orderByTerms, series.metrics).replace( + orderByTerms, sortAggKey ); overwrite(doc, `aggs.${series.id}.terms.order`, { [bucketPath]: direction }); overwrite(doc, `aggs.${series.id}.aggs`, { [sortAggKey]: fn(metric) }); - } else if (['_key', '_count'].includes(series.terms_order_by)) { - overwrite(doc, `aggs.${series.id}.terms.order`, { [series.terms_order_by]: direction }); + } else if (['_key', '_count'].includes(orderByTerms)) { + overwrite(doc, `aggs.${series.id}.terms.order`, { [orderByTerms]: direction }); } else { overwrite(doc, `aggs.${series.id}.terms.order`, { _count: direction }); } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js index ba65e583cc094..7dfc0cec74d12 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js @@ -23,7 +23,7 @@ import { isLastValueTimerangeMode } from '../../helpers/get_timerange_mode'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { getTimerange } from '../../helpers/get_timerange'; import { calculateAggRoot } from './calculate_agg_root'; -import { search } from '../../../../../../../plugins/data/server'; +import { search, UI_SETTINGS } from '../../../../../../../plugins/data/server'; const { dateHistogramInterval } = search.aggs; export function dateHistogram( @@ -32,12 +32,14 @@ export function dateHistogram( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const { timeField, interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); const meta = { timeField, + index: indexPatternObject?.title, }; const getDateHistogramForLastBucketMode = () => { @@ -65,7 +67,7 @@ export function dateHistogram( }); overwrite(doc, aggRoot.replace(/\.aggs$/, '.meta'), { - timeField, + ...meta, intervalString, bucketSize, }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js index 13874166bc558..0166537146e0b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js @@ -17,12 +17,13 @@ * under the License. */ -const filter = (metric) => metric.type === 'filter_ratio'; import { esQuery } from '../../../../../../data/server'; import { bucketTransform } from '../../helpers/bucket_transform'; import { overwrite } from '../../helpers'; import { calculateAggRoot } from './calculate_agg_root'; +const filter = (metric) => metric.type === 'filter_ratio'; + export function ratios(req, panel, esQueryConfig, indexPatternObject) { return (next) => (doc) => { panel.series.forEach((column) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js index fe6a8b537d64b..c5501233f8135 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js @@ -22,6 +22,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { bucketTransform } from '../../helpers/bucket_transform'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { calculateAggRoot } from './calculate_agg_root'; +import { UI_SETTINGS } from '../../../../../../data/common'; export function metricBuckets( req, @@ -29,9 +30,10 @@ export function metricBuckets( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/pivot.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/pivot.js index ad085f25cf451..8ae50f62ca210 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/pivot.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/pivot.js @@ -27,6 +27,7 @@ import { bucketTransform } from '../../helpers/bucket_transform'; export function pivot(req, panel) { return (next) => (doc) => { const { sort } = req.payload.state; + if (panel.pivot_id) { overwrite(doc, 'aggs.pivot.terms.field', panel.pivot_id); overwrite(doc, 'aggs.pivot.terms.size', panel.pivot_rows); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js index 6cf165d124e26..914b246bc8fdf 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js @@ -21,6 +21,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { calculateAggRoot } from './calculate_agg_root'; import { createPositiveRate, filter } from '../series/positive_rate'; +import { UI_SETTINGS } from '../../../../../../data/common'; export function positiveRate( req, @@ -28,9 +29,10 @@ export function positiveRate( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js index ba08b18256dec..1333cecc36a92 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js @@ -22,6 +22,7 @@ import { getBucketSize } from '../../helpers/get_bucket_size'; import { bucketTransform } from '../../helpers/bucket_transform'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { calculateAggRoot } from './calculate_agg_root'; +import { UI_SETTINGS } from '../../../../../../data/common'; export function siblingBuckets( req, @@ -29,9 +30,10 @@ export function siblingBuckets( esQueryConfig, indexPatternObject, capabilities, - { barTargetUiSettings } + uiSettings ) { - return (next) => (doc) => { + return (next) => async (doc) => { + const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); const { bucketSize } = getBucketSize(req, interval, capabilities, barTargetUiSettings); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js index f8752ce8fa3a8..2e4c05273ee3f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js @@ -25,8 +25,8 @@ import { getSplits } from '../../helpers/get_splits'; import { mapBucket } from '../../helpers/map_bucket'; import { evaluate } from 'tinymath'; -export function mathAgg(resp, panel, series, meta) { - return (next) => (results) => { +export function mathAgg(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const mathMetric = last(series.metrics); if (mathMetric.type !== 'math') return next(results); // Filter the results down to only the ones that match the series.id. Sometimes @@ -38,7 +38,7 @@ export function mathAgg(resp, panel, series, meta) { return true; }); const decoration = getDefaultDecoration(series); - const splits = getSplits(resp, panel, series, meta); + const splits = await getSplits(resp, panel, series, meta, extractFields); const mathSeries = splits.map((split) => { if (mathMetric.variables.length) { // Gather the data for the splits. The data will either be a sibling agg or diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.test.js index 79cfd2ddd54bb..c65571379d50a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.test.js @@ -91,15 +91,16 @@ describe('math(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - mathAgg(resp, panel, series)(next)([]); + await mathAgg(resp, panel, series)(next)([]); expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { - const next = mathAgg(resp, panel, series)((results) => results); - const results = stdMetric(resp, panel, series)(next)([]); + test('creates a series', async () => { + const next = await mathAgg(resp, panel, series)((results) => results); + const results = await stdMetric(resp, panel, series)(next)([]); + expect(results).toHaveLength(1); expect(results[0]).toEqual({ @@ -118,12 +119,12 @@ describe('math(resp, panel, series)', () => { }); }); - test('turns division by zero into null values', () => { + test('turns division by zero into null values', async () => { resp.aggregations.test.buckets[0].timeseries.buckets[0].mincpu = 0; - const next = mathAgg(resp, panel, series)((results) => results); - const results = stdMetric(resp, panel, series)(next)([]); - expect(results).toHaveLength(1); + const next = await mathAgg(resp, panel, series)((results) => results); + const results = await stdMetric(resp, panel, series)(next)([]); + expect(results).toHaveLength(1); expect(results[0]).toEqual( expect.objectContaining({ data: [ @@ -134,15 +135,35 @@ describe('math(resp, panel, series)', () => { ); }); - test('throws on actual tinymath expression errors', () => { + test('throws on actual tinymath expression errors #1', async () => { series.metrics[2].script = 'notExistingFn(params.a)'; - expect(() => - stdMetric(resp, panel, series)(mathAgg(resp, panel, series)((results) => results))([]) - ).toThrow(); + try { + await stdMetric( + resp, + panel, + series + )(await mathAgg(resp, panel, series)((results) => results))([]); + } catch (e) { + expect(e.message).toEqual( + 'Failed to parse expression. Expected "*", "+", "-", "/", or end of input but "(" found.' + ); + } + }); + + test('throws on actual tinymath expression errors #2', async () => { series.metrics[2].script = 'divide(params.a, params.b'; - expect(() => - stdMetric(resp, panel, series)(mathAgg(resp, panel, series)((results) => results))([]) - ).toThrow(); + + try { + await stdMetric( + resp, + panel, + series + )(await mathAgg(resp, panel, series)((results) => results))([]); + } catch (e) { + expect(e.message).toEqual( + 'Failed to parse expression. Expected "*", "+", "-", "/", or end of input but "(" found.' + ); + } }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.js index 2e0d176f80b23..6703202ef6b49 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.js @@ -23,15 +23,15 @@ import { getSplits } from '../../helpers/get_splits'; import { getLastMetric } from '../../helpers/get_last_metric'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function percentile(resp, panel, series, meta) { - return (next) => (results) => { +export function percentile(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type !== METRIC_TYPES.PERCENTILE) { return next(results); } - getSplits(resp, panel, series, meta).forEach((split) => { + (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { metric.percentiles.forEach((percentile) => { const percentileValue = percentile.value ? percentile.value : 0; const id = `${split.id}:${percentile.id}`; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js index d239cb2138fe1..225cc5e261a3a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js @@ -80,15 +80,18 @@ describe('percentile(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - percentile(resp, panel, series)(next)([]); + + await percentile(resp, panel, series, {})(next)([]); + expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { + test('creates a series', async () => { const next = (results) => results; - const results = percentile(resp, panel, series)(next)([]); + const results = await percentile(resp, panel, series, {})(next)([]); + expect(results).toHaveLength(2); expect(results[0]).toHaveProperty('id', 'test:10-90'); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile_rank.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile_rank.js index c163605af7ac5..7660dd80d143d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile_rank.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile_rank.js @@ -23,15 +23,15 @@ import { getLastMetric } from '../../helpers/get_last_metric'; import { toPercentileNumber } from '../../../../../common/to_percentile_number'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function percentileRank(resp, panel, series, meta) { - return (next) => (results) => { +export function percentileRank(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type !== METRIC_TYPES.PERCENTILE_RANK) { return next(results); } - getSplits(resp, panel, series, meta).forEach((split) => { + (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { (metric.values || []).forEach((percentileRank, index) => { const data = split.timeseries.buckets.map((bucket) => [ bucket.key, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.js index d2b0ce9226bb9..07aebea78a1fb 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.js @@ -22,8 +22,8 @@ import _ from 'lodash'; import { getDefaultDecoration } from '../../helpers/get_default_decoration'; import { calculateLabel } from '../../../../../common/calculate_label'; -export function seriesAgg(resp, panel, series) { - return (next) => (results) => { +export function seriesAgg(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { if (series.metrics.some((m) => m.type === 'series_agg')) { const decoration = getDefaultDecoration(series); @@ -43,9 +43,14 @@ export function seriesAgg(resp, panel, series) { const fn = SeriesAgg[m.function]; return (fn && fn(acc)) || acc; }, targetSeries); + + const fieldsForMetaIndex = meta.index ? await extractFields(meta.index) : []; + results.push({ id: `${series.id}`, - label: series.label || calculateLabel(_.last(series.metrics), series.metrics), + label: + series.label || + calculateLabel(_.last(series.metrics), series.metrics, fieldsForMetaIndex), color: series.color, data: _.first(data), ...decoration, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js index b458eee17bce5..ddf4f620f0657 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js @@ -91,15 +91,16 @@ describe('seriesAgg(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - seriesAgg(resp, panel, series)(next)([]); + await seriesAgg(resp, panel, series, {})(next)([]); expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { - const next = seriesAgg(resp, panel, series)((results) => results); - const results = stdMetric(resp, panel, series)(next)([]); + test('creates a series', async () => { + const next = await seriesAgg(resp, panel, series, {})((results) => results); + const results = await stdMetric(resp, panel, series, {})(next)([]); + expect(results).toHaveLength(1); expect(results[0]).toEqual({ diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.js index be95913c6ec38..ffc3d2636d1af 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.js @@ -20,36 +20,38 @@ import { getAggValue, getLastMetric, getSplits } from '../../helpers'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function stdDeviationBands(resp, panel, series, meta) { - return (next) => (results) => { +export function stdDeviationBands(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type === METRIC_TYPES.STD_DEVIATION && metric.mode === 'band') { - getSplits(resp, panel, series, meta).forEach(({ id, color, label, timeseries }) => { - const data = timeseries.buckets.map((bucket) => [ - bucket.key, - getAggValue(bucket, { ...metric, mode: 'upper' }), - getAggValue(bucket, { ...metric, mode: 'lower' }), - ]); + (await getSplits(resp, panel, series, meta, extractFields)).forEach( + ({ id, color, label, timeseries }) => { + const data = timeseries.buckets.map((bucket) => [ + bucket.key, + getAggValue(bucket, { ...metric, mode: 'upper' }), + getAggValue(bucket, { ...metric, mode: 'lower' }), + ]); - results.push({ - id, - label, - color, - data, - lines: { - show: series.chart_type === 'line', - fill: 0.5, - lineWidth: 0, - mode: 'band', - }, - bars: { - show: series.chart_type === 'bar', - fill: 0.5, - mode: 'band', - }, - points: { show: false }, - }); - }); + results.push({ + id, + label, + color, + data, + lines: { + show: series.chart_type === 'line', + fill: 0.5, + lineWidth: 0, + mode: 'band', + }, + bars: { + show: series.chart_type === 'bar', + fill: 0.5, + mode: 'band', + }, + points: { show: false }, + }); + } + ); } return next(results); }; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js index 4899eaed2611a..97d0cc8a84f72 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js @@ -77,15 +77,15 @@ describe('stdDeviationBands(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - stdDeviationBands(resp, panel, series)(next)([]); + await stdDeviationBands(resp, panel, series, {})(next)([]); expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { + test('creates a series', async () => { const next = (results) => results; - const results = stdDeviationBands(resp, panel, series)(next)([]); + const results = await stdDeviationBands(resp, panel, series, {})(next)([]); expect(results).toHaveLength(1); expect(results[0]).toEqual({ diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.js index 321e1c5125e1c..652cd2feb979a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.js @@ -19,11 +19,11 @@ import { getSplits, getLastMetric, getSiblingAggValue } from '../../helpers'; -export function stdDeviationSibling(resp, panel, series, meta) { - return (next) => (results) => { +export function stdDeviationSibling(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.mode === 'band' && metric.type === 'std_deviation_bucket') { - getSplits(resp, panel, series, meta).forEach((split) => { + (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { const data = split.timeseries.buckets.map((bucket) => [ bucket.key, getSiblingAggValue(split, { ...metric, mode: 'upper' }), diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js index b6acf822bc242..93386a008ae96 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js @@ -77,15 +77,15 @@ describe('stdDeviationSibling(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - stdDeviationSibling(resp, panel, series)(next)([]); + await stdDeviationSibling(resp, panel, series, {})(next)([]); expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { + test('creates a series', async () => { const next = (results) => results; - const results = stdDeviationSibling(resp, panel, series)(next)([]); + const results = await stdDeviationSibling(resp, panel, series, {})(next)([]); expect(results).toHaveLength(1); expect(results[0]).toEqual({ diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js index e04c3a93e81bb..9b9dacd1af957 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js @@ -23,8 +23,8 @@ import { getLastMetric } from '../../helpers/get_last_metric'; import { mapBucket } from '../../helpers/map_bucket'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function stdMetric(resp, panel, series, meta) { - return (next) => (results) => { +export function stdMetric(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type === METRIC_TYPES.STD_DEVIATION && metric.mode === 'band') { return next(results); @@ -35,17 +35,20 @@ export function stdMetric(resp, panel, series, meta) { } if (/_bucket$/.test(metric.type)) return next(results); const decoration = getDefaultDecoration(series); - getSplits(resp, panel, series, meta).forEach((split) => { + + (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { const data = split.timeseries.buckets.map(mapBucket(metric)); results.push({ id: `${split.id}`, label: split.label, + splitByLabel: split.splitByLabel, labelFormatted: split.labelFormatted, color: split.color, data, ...decoration, }); }); + return next(results); }; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js index 78a29c04732d7..07590ba359bfe 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js @@ -58,32 +58,38 @@ describe('stdMetric(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - stdMetric(resp, panel, series)(next)([]); + await stdMetric(resp, panel, series, {})(next)([]); + expect(next.mock.calls.length).toEqual(1); }); - test('calls next when finished (percentile)', () => { + test('calls next when finished (percentile)', async () => { series.metrics[0].type = 'percentile'; + const next = jest.fn((d) => d); - const results = stdMetric(resp, panel, series)(next)([]); + const results = await stdMetric(resp, panel, series, {})(next)([]); + expect(next.mock.calls.length).toEqual(1); expect(results).toHaveLength(0); }); - test('calls next when finished (std_deviation band)', () => { + test('calls next when finished (std_deviation band)', async () => { series.metrics[0].type = 'std_deviation'; series.metrics[0].mode = 'band'; + const next = jest.fn((d) => d); - const results = stdMetric(resp, panel, series)(next)([]); + const results = await stdMetric(resp, panel, series, {})(next)([]); + expect(next.mock.calls.length).toEqual(1); expect(results).toHaveLength(0); }); - test('creates a series', () => { + test('creates a series', async () => { const next = (results) => results; - const results = stdMetric(resp, panel, series)(next)([]); + const results = await stdMetric(resp, panel, series, {})(next)([]); + expect(results).toHaveLength(1); expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); expect(results[0]).toHaveProperty('id', 'test'); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.js index b5d972a38769e..80f1f6c404724 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.js @@ -22,15 +22,15 @@ import { getSplits } from '../../helpers/get_splits'; import { getLastMetric } from '../../helpers/get_last_metric'; import { getSiblingAggValue } from '../../helpers/get_sibling_agg_value'; -export function stdSibling(resp, panel, series, meta) { - return (next) => (results) => { +export function stdSibling(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (!/_bucket$/.test(metric.type)) return next(results); if (metric.type === 'std_deviation_bucket' && metric.mode === 'band') return next(results); const decoration = getDefaultDecoration(series); - getSplits(resp, panel, series, meta).forEach((split) => { + (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { const data = split.timeseries.buckets.map((bucket) => { return [bucket.key, getSiblingAggValue(split, metric)]; }); @@ -42,6 +42,7 @@ export function stdSibling(resp, panel, series, meta) { ...decoration, }); }); + return next(results); }; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js index d99ae6771c437..52edb8408b5bd 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js @@ -72,23 +72,23 @@ describe('stdSibling(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - stdSibling(resp, panel, series)(next)([]); + await stdSibling(resp, panel, series, {})(next)([]); expect(next.mock.calls.length).toEqual(1); }); - test('calls next when std. deviation bands set', () => { + test('calls next when std. deviation bands set', async () => { series.metrics[1].mode = 'band'; const next = jest.fn((results) => results); - const results = stdSibling(resp, panel, series)(next)([]); + const results = await stdSibling(resp, panel, series, {})(next)([]); expect(next.mock.calls.length).toEqual(1); expect(results).toHaveLength(0); }); - test('creates a series', () => { + test('creates a series', async () => { const next = (results) => results; - const results = stdSibling(resp, panel, series)(next)([]); + const results = await stdSibling(resp, panel, series, {})(next)([]); expect(results).toHaveLength(1); expect(results[0]).toEqual({ diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js index 57c1a8aead7dc..019d5d32c1c30 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js @@ -60,15 +60,17 @@ describe('timeShift(resp, panel, series)', () => { }; }); - test('calls next when finished', () => { + test('calls next when finished', async () => { const next = jest.fn(); - timeShift(resp, panel, series)(next)([]); + await timeShift(resp, panel, series, {})(next)([]); + expect(next.mock.calls.length).toEqual(1); }); - test('creates a series', () => { - const next = timeShift(resp, panel, series)((results) => results); - const results = stdMetric(resp, panel, series)(next)([]); + test('creates a series', async () => { + const next = await timeShift(resp, panel, series, {})((results) => results); + const results = await stdMetric(resp, panel, series, {})(next)([]); + expect(results).toHaveLength(1); expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); expect(results[0]).toHaveProperty('id', 'test'); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/index.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/index.js index cbd775bcd816b..ee4161288673c 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/index.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/index.js @@ -17,7 +17,6 @@ * under the License. */ -// import percentile from './percentile'; import { stdMetric } from './std_metric'; import { stdSibling } from './std_sibling'; import { seriesAgg } from './series_agg'; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile.js index 788bb6f14a0c7..33af66855ef3b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile.js @@ -22,8 +22,8 @@ import { getLastMetric } from '../../helpers/get_last_metric'; import { toPercentileNumber } from '../../../../../common/to_percentile_number'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function percentile(bucket, panel, series) { - return (next) => (results) => { +export function percentile(bucket, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type !== METRIC_TYPES.PERCENTILE) { @@ -34,7 +34,7 @@ export function percentile(bucket, panel, series) { aggregations: bucket, }; - getSplits(fakeResp, panel, series).forEach((split) => { + (await getSplits(fakeResp, panel, series, meta, extractFields)).forEach((split) => { // table allows only one percentile in a series (the last one will be chosen in case of several) const percentile = last(metric.percentiles); const percentileKey = toPercentileNumber(percentile.value); @@ -45,6 +45,7 @@ export function percentile(bucket, panel, series) { results.push({ id: split.id, + label: `${split.label} (${percentile.value ?? 0})`, data, }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile_rank.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile_rank.js index c280538c7ce5f..c902631aaf47b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile_rank.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/percentile_rank.js @@ -23,8 +23,8 @@ import { toPercentileNumber } from '../../../../../common/to_percentile_number'; import { getAggValue } from '../../helpers/get_agg_value'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function percentileRank(bucket, panel, series) { - return (next) => (results) => { +export function percentileRank(bucket, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type !== METRIC_TYPES.PERCENTILE_RANK) { @@ -35,7 +35,7 @@ export function percentileRank(bucket, panel, series) { aggregations: bucket, }; - getSplits(fakeResp, panel, series).forEach((split) => { + (await getSplits(fakeResp, panel, series, meta, extractFields)).forEach((split) => { // table allows only one percentile rank in a series (the last one will be chosen in case of several) const lastRankValue = last(metric.values); const percentileRank = toPercentileNumber(lastRankValue); @@ -51,7 +51,7 @@ export function percentileRank(bucket, panel, series) { results.push({ data, id: split.id, - label: `${split.label} (${percentileRank || 0})`, + label: `${split.label} (${lastRankValue ?? 0})`, }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/series_agg.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/series_agg.js index 343198bc22a6e..56a3207cd115a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/series_agg.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/series_agg.js @@ -21,8 +21,8 @@ import { SeriesAgg } from './_series_agg'; import _ from 'lodash'; import { calculateLabel } from '../../../../../common/calculate_label'; -export function seriesAgg(resp, panel, series) { - return (next) => (results) => { +export function seriesAgg(resp, panel, series, meta, extractFields) { + return (next) => async (results) => { if (series.aggregate_by && series.aggregate_function) { const targetSeries = []; // Filter out the seires with the matching metric and store them @@ -36,9 +36,14 @@ export function seriesAgg(resp, panel, series) { }); const fn = SeriesAgg[series.aggregate_function]; const data = fn(targetSeries); + + const fieldsForMetaIndex = meta.index ? await extractFields(meta.index) : []; + results.push({ id: `${series.id}`, - label: series.label || calculateLabel(_.last(series.metrics), series.metrics), + label: + series.label || + calculateLabel(_.last(series.metrics), series.metrics, fieldsForMetaIndex), data: _.first(data), }); } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js index 2242b338e7b92..6f7e8b0edd10d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js @@ -22,8 +22,8 @@ import { getLastMetric } from '../../helpers/get_last_metric'; import { mapBucket } from '../../helpers/map_bucket'; import { METRIC_TYPES } from '../../../../../common/metric_types'; -export function stdMetric(bucket, panel, series) { - return (next) => (results) => { +export function stdMetric(bucket, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (metric.type === METRIC_TYPES.STD_DEVIATION && metric.mode === 'band') { @@ -42,7 +42,7 @@ export function stdMetric(bucket, panel, series) { aggregations: bucket, }; - getSplits(fakeResp, panel, series).forEach((split) => { + (await getSplits(fakeResp, panel, series, meta, extractFields)).forEach((split) => { const data = split.timeseries.buckets.map(mapBucket(metric)); results.push({ id: split.id, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_sibling.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_sibling.js index 17cfac6e8895b..001da9019f116 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_sibling.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_sibling.js @@ -21,15 +21,15 @@ import { getSplits } from '../../helpers/get_splits'; import { getLastMetric } from '../../helpers/get_last_metric'; import { getSiblingAggValue } from '../../helpers/get_sibling_agg_value'; -export function stdSibling(bucket, panel, series) { - return (next) => (results) => { +export function stdSibling(bucket, panel, series, meta, extractFields) { + return (next) => async (results) => { const metric = getLastMetric(series); if (!/_bucket$/.test(metric.type)) return next(results); if (metric.type === 'std_deviation_bucket' && metric.mode === 'band') return next(results); const fakeResp = { aggregations: bucket }; - getSplits(fakeResp, panel, series).forEach((split) => { + (await getSplits(fakeResp, panel, series, meta, extractFields)).forEach((split) => { const data = split.timeseries.buckets.map((b) => { return [b.key, getSiblingAggValue(split, metric)]; }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts index 6b2ef320d54b7..64cd3bf7a7dea 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts @@ -78,7 +78,7 @@ const body = JSON.parse(` `); describe('buildRequestBody(req)', () => { - test('returns a valid body', () => { + test('returns a valid body', async () => { const panel = body.panels[0]; const series = panel.series[0]; const getValidTimeInterval = jest.fn(() => '10s'); @@ -91,14 +91,16 @@ describe('buildRequestBody(req)', () => { queryStringOptions: {}, }; const indexPatternObject = {}; - const doc = buildRequestBody( + const doc = await buildRequestBody( { payload: body }, panel, series, config, indexPatternObject, capabilities, - { barTargetUiSettings: 50 } + { + get: async () => 50, + } ); expect(doc).toEqual({ diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts index 9d8f3fca789f0..45d3d788df4f3 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts @@ -34,8 +34,8 @@ import { processors } from '../request_processors/series/index'; * ] * @returns {Object} doc - processed body */ -export function buildRequestBody(...args: any[]) { +export async function buildRequestBody(...args: any[]) { const processor = buildProcessorFunction(processors, ...args); - const doc = processor({}); + const doc = await processor({}); return doc; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.js index 3804b1407b086..ca4f631f9ea70 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.js @@ -19,7 +19,6 @@ import { buildRequestBody } from './build_request_body'; import { getEsShardTimeout } from '../helpers/get_es_shard_timeout'; import { getIndexPatternObject } from '../helpers/get_index_pattern'; -import { UI_SETTINGS } from '../../../../../data/common'; export async function getSeriesRequestParams(req, panel, series, esQueryConfig, capabilities) { const uiSettings = req.getUiSettingsService(); @@ -27,17 +26,14 @@ export async function getSeriesRequestParams(req, panel, series, esQueryConfig, (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; const { indexPatternObject, indexPatternString } = await getIndexPatternObject(req, indexPattern); - const request = buildRequestBody( + const request = await buildRequestBody( req, panel, series, esQueryConfig, indexPatternObject, capabilities, - { - maxBarsUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), - barTargetUiSettings: await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), - } + uiSettings ); const esShardTimeout = await getEsShardTimeout(req); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.js index eef7143990e98..c04e56de57a4e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.js @@ -21,9 +21,10 @@ import { buildProcessorFunction } from '../build_processor_function'; import { processors } from '../response_processors/series'; import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { createFieldsFetcher } from './../helpers/fields_fetcher'; -export function handleResponseBody(panel) { - return (resp) => { +export function handleResponseBody(panel, req, searchStrategy, capabilities) { + return async (resp) => { if (resp.error) { const err = new Error(resp.error.type); err.response = JSON.stringify(resp); @@ -48,8 +49,11 @@ export function handleResponseBody(panel) { const [seriesId] = keys; const meta = get(resp, `aggregations.${seriesId}.meta`, {}); const series = panel.series.find((s) => s.id === (meta.seriesId || seriesId)); - const processor = buildProcessorFunction(processors, resp, panel, series, meta); - return processor([]); + const extractFields = createFieldsFetcher(req, searchStrategy, capabilities); + + const processor = buildProcessorFunction(processors, resp, panel, series, meta, extractFields); + + return await processor([]); }; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/build_request_body.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/build_request_body.js index 7715c803d374b..3fcf38bb07e20 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/build_request_body.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/build_request_body.js @@ -20,8 +20,8 @@ import { buildProcessorFunction } from '../build_processor_function'; import { processors } from '../request_processors/table'; -export function buildRequestBody(...args) { +export async function buildRequestBody(...args) { const processor = buildProcessorFunction(processors, ...args); - const doc = processor({}); + const doc = await processor({}); return doc; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js index 909cee456c31f..9604904af2c7d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.js @@ -34,27 +34,40 @@ function trendSinceLastBucket(data) { return Number.isNaN(trend) ? 0 : trend; } -export function processBucket(panel) { - return (bucket) => { - const series = getActiveSeries(panel).map((series) => { - const timeseries = get(bucket, `${series.id}.timeseries`); - const buckets = get(bucket, `${series.id}.buckets`); +export function processBucket(panel, req, searchStrategy, capabilities, extractFields) { + return async (bucket) => { + const series = await Promise.all( + getActiveSeries(panel).map(async (series) => { + const timeseries = get(bucket, `${series.id}.timeseries`); + const buckets = get(bucket, `${series.id}.buckets`); + let meta = {}; + + if (!timeseries && buckets) { + meta = get(bucket, `${series.id}.meta`); + const timeseries = { + buckets: get(bucket, `${series.id}.buckets`), + }; + overwrite(bucket, series.id, { meta, timeseries }); + } + + const processor = buildProcessorFunction( + processors, + bucket, + panel, + series, + meta, + extractFields + ); + const result = first(await processor([])); + + if (!result) return null; + const data = get(result, 'data', []); + result.slope = trendSinceLastBucket(data); + result.last = getLastValue(data); + return result; + }) + ); - if (!timeseries && buckets) { - const meta = get(bucket, `${series.id}.meta`); - const timeseries = { - buckets: get(bucket, `${series.id}.buckets`), - }; - overwrite(bucket, series.id, { meta, timeseries }); - } - const processor = buildProcessorFunction(processors, bucket, panel, series); - const result = first(processor([])); - if (!result) return null; - const data = get(result, 'data', []); - result.slope = trendSinceLastBucket(data); - result.last = getLastValue(data); - return result; - }); return { key: bucket.key, series }; }; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.test.js index a4f9c71a5953d..83479468e7199 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/table/process_bucket.test.js @@ -94,17 +94,17 @@ describe('processBucket(panel)', () => { panel = createPanel([SERIES_ID]); }); - test('return the correct trend direction', () => { + test('return the correct trend direction', async () => { const bucketProcessor = processBucket(panel); const buckets = createBuckets([SERIES_ID]); for (const bucket of buckets) { - const result = bucketProcessor(bucket); + const result = await bucketProcessor(bucket); expect(result.key).toEqual(bucket.key); expect(trendChecker(bucket.expectedTrend, result.series[0].slope)).toBeTruthy(); } }); - test('properly handle 0 values for trend', () => { + test('properly handle 0 values for trend', async () => { const bucketProcessor = processBucket(panel); const bucketforNaNResult = { key: 'NaNScenario', @@ -121,16 +121,18 @@ describe('processBucket(panel)', () => { ], }, }; - const result = bucketProcessor(bucketforNaNResult); + const result = await bucketProcessor(bucketforNaNResult); expect(result.key).toEqual(bucketforNaNResult.key); expect(trendChecker(bucketforNaNResult.expectedTrend, result.series[0].slope)).toEqual(true); }); - test('have the side effect to create the timeseries property if missing on bucket', () => { + test('have the side effect to create the timeseries property if missing on bucket', async () => { const bucketProcessor = processBucket(panel); const buckets = createBuckets([SERIES_ID]); + for (const bucket of buckets) { - bucketProcessor(bucket); + await bucketProcessor(bucket); + expect(bucket[SERIES_ID].buckets).toBeUndefined(); expect(bucket[SERIES_ID].timeseries).toBeDefined(); } @@ -145,11 +147,12 @@ describe('processBucket(panel)', () => { panel = createPanel(SERIES); }); - test('return the correct trend direction', () => { + test('return the correct trend direction', async () => { const bucketProcessor = processBucket(panel); const buckets = createBuckets(SERIES); for (const bucket of buckets) { - const result = bucketProcessor(bucket); + const result = await bucketProcessor(bucket); + expect(result.key).toEqual(bucket.key); expect(trendChecker(bucket.expectedTrend, result.series[0].slope)).toBeTruthy(); expect(trendChecker(bucket.expectedTrend, result.series[1].slope)).toBeTruthy(); diff --git a/src/plugins/vis_type_timeseries/tsconfig.json b/src/plugins/vis_type_timeseries/tsconfig.json new file mode 100644 index 0000000000000..7b2dd4b608c1c --- /dev/null +++ b/src/plugins/vis_type_timeseries/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "*.ts" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../visualize/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_vega/public/data_model/search_api.ts b/src/plugins/vis_type_vega/public/data_model/search_api.ts index be58e3e3951eb..1a91079848eba 100644 --- a/src/plugins/vis_type_vega/public/data_model/search_api.ts +++ b/src/plugins/vis_type_vega/public/data_model/search_api.ts @@ -40,7 +40,8 @@ export class SearchAPI { constructor( private readonly dependencies: SearchAPIDependencies, private readonly abortSignal?: AbortSignal, - public readonly inspectorAdapters?: VegaInspectorAdapters + public readonly inspectorAdapters?: VegaInspectorAdapters, + private readonly searchSessionId?: string ) {} search(searchRequests: SearchRequest[]) { @@ -60,10 +61,7 @@ export class SearchAPI { } return search - .search( - { params }, - { abortSignal: this.abortSignal, sessionId: search.session.getSessionId() } - ) + .search({ params }, { abortSignal: this.abortSignal, sessionId: this.searchSessionId }) .pipe( tap((data) => this.inspectSearchResult(data, requestResponders[requestId])), map((data) => ({ diff --git a/src/plugins/vis_type_vega/public/vega_fn.ts b/src/plugins/vis_type_vega/public/vega_fn.ts index 5a8113aeeea11..70f01aa65f822 100644 --- a/src/plugins/vis_type_vega/public/vega_fn.ts +++ b/src/plugins/vis_type_vega/public/vega_fn.ts @@ -74,6 +74,7 @@ export const createVegaFn = ( query: get(input, 'query') as Query, filters: get(input, 'filters') as any, visParams: { spec: args.spec }, + searchSessionId: context.getSearchSessionId(), }); return { diff --git a/src/plugins/vis_type_vega/public/vega_request_handler.ts b/src/plugins/vis_type_vega/public/vega_request_handler.ts index f48b61ed70822..1f60feebe7efa 100644 --- a/src/plugins/vis_type_vega/public/vega_request_handler.ts +++ b/src/plugins/vis_type_vega/public/vega_request_handler.ts @@ -32,6 +32,7 @@ interface VegaRequestHandlerParams { filters: Filter; timeRange: TimeRange; visParams: VisParams; + searchSessionId?: string; } interface VegaRequestHandlerContext { @@ -52,6 +53,7 @@ export function createVegaRequestHandler( filters, query, visParams, + searchSessionId, }: VegaRequestHandlerParams) { if (!searchAPI) { searchAPI = new SearchAPI( @@ -61,7 +63,8 @@ export function createVegaRequestHandler( injectedMetadata: getInjectedMetadata(), }, context.abortSignal, - context.inspectorAdapters + context.inspectorAdapters, + searchSessionId ); } diff --git a/src/plugins/vis_type_vislib/public/to_ast.test.ts b/src/plugins/vis_type_vislib/public/to_ast.test.ts index 48d3dfe254d0b..28049be291723 100644 --- a/src/plugins/vis_type_vislib/public/to_ast.test.ts +++ b/src/plugins/vis_type_vislib/public/to_ast.test.ts @@ -22,7 +22,7 @@ import { buildExpression } from '../../expressions/public'; import { BasicVislibParams } from './types'; import { toExpressionAst } from './to_ast'; -import { sampleAreaVis } from './sample_vis.test.mocks'; +import { sampleAreaVis } from '../../vis_type_xy/public/sample_vis.test.mocks'; jest.mock('../../expressions/public', () => ({ ...(jest.requireActual('../../expressions/public') as any), diff --git a/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts b/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts index 36a9a17341bc5..08a74a37f380c 100644 --- a/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts +++ b/src/plugins/vis_type_vislib/public/to_ast_pie.test.ts @@ -21,7 +21,7 @@ import { Vis } from '../../visualizations/public'; import { buildExpression } from '../../expressions/public'; import { PieVisParams } from './pie'; -import { samplePieVis } from './sample_vis.test.mocks'; +import { samplePieVis } from '../../vis_type_xy/public/sample_vis.test.mocks'; import { toExpressionAst } from './to_ast_pie'; jest.mock('../../expressions/public', () => ({ diff --git a/src/plugins/vis_type_vislib/public/vis_controller.tsx b/src/plugins/vis_type_vislib/public/vis_controller.tsx index 2a32d19874c22..a536ac4b207ea 100644 --- a/src/plugins/vis_type_vislib/public/vis_controller.tsx +++ b/src/plugins/vis_type_vislib/public/vis_controller.tsx @@ -44,8 +44,8 @@ export const createVislibVisController = ( charts: ChartsPluginSetup ) => { return class VislibVisController { - private removeListeners?: () => void; - private unmountLegend?: () => void; + removeListeners?: () => void; + unmountLegend?: () => void; legendRef: RefObject; container: HTMLDivElement; diff --git a/src/plugins/vis_type_vislib/tsconfig.json b/src/plugins/vis_type_vislib/tsconfig.json new file mode 100644 index 0000000000000..74bc1440d9dbc --- /dev/null +++ b/src/plugins/vis_type_vislib/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../kibana_legacy/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + { "path": "../vis_type_xy/tsconfig.json" }, + ] +} diff --git a/src/plugins/vis_type_xy/public/editor/components/options/point_series/elastic_charts_options.tsx b/src/plugins/vis_type_xy/public/editor/components/options/point_series/elastic_charts_options.tsx index a3e573741644c..08fd0155b0d4b 100644 --- a/src/plugins/vis_type_xy/public/editor/components/options/point_series/elastic_charts_options.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/point_series/elastic_charts_options.tsx @@ -17,20 +17,26 @@ * under the License. */ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE } from '@kbn/analytics'; -import { SelectOption, SwitchOption } from '../../../../../../vis_default_editor/public'; +import { + SelectOption, + SwitchOption, + PalettePicker, +} from '../../../../../../vis_default_editor/public'; +import { PaletteRegistry } from '../../../../../../charts/public'; import { ChartType } from '../../../../../common'; import { VisParams } from '../../../../types'; import { ValidationVisOptionsProps } from '../../common'; -import { getTrackUiMetric } from '../../../../services'; +import { getPalettesService, getTrackUiMetric } from '../../../../services'; export function ElasticChartsOptions(props: ValidationVisOptionsProps) { const trackUiMetric = getTrackUiMetric(); + const [palettesRegistry, setPalettesRegistry] = useState(null); const { stateParams, setValue, vis, aggs } = props; const hasLineChart = stateParams.seriesParams.some( @@ -39,6 +45,14 @@ export function ElasticChartsOptions(props: ValidationVisOptionsProps aggs.aggs.find(({ id }) => id === paramId)?.enabled ); + useEffect(() => { + const fetchPalettes = async () => { + const palettes = await getPalettesService().getPalettes(); + setPalettesRegistry(palettes); + }; + fetchPalettes(); + }, []); + return ( <> }} /> )} + + {palettesRegistry && ( + { + if (trackUiMetric) { + trackUiMetric(METRIC_TYPE.CLICK, 'palette_selected'); + } + setValue(paramName, value); + }} + /> + )} ); } diff --git a/src/plugins/vis_type_xy/public/plugin.ts b/src/plugins/vis_type_xy/public/plugin.ts index ab22ae57ebbdf..cdacc1bfaca6a 100644 --- a/src/plugins/vis_type_xy/public/plugin.ts +++ b/src/plugins/vis_type_xy/public/plugin.ts @@ -29,10 +29,10 @@ import { setDataActions, setFormatService, setThemeService, - setColorsService, setTimefilter, setUISettings, setDocLinks, + setPalettesService, setTrackUiMetric, } from './services'; import { visTypesDefinitions } from './vis_types'; @@ -77,8 +77,7 @@ export class VisTypeXyPlugin if (!core.uiSettings.get(LEGACY_CHARTS_LIBRARY, false)) { setUISettings(core.uiSettings); setThemeService(charts.theme); - setColorsService(charts.legacyColors); - + setPalettesService(charts.palettes); [createVisTypeXyVisFn].forEach(expressions.registerFunction); expressions.registerRenderer(xyVisRenderer); visTypesDefinitions.forEach(visualizations.createBaseVisualization); diff --git a/src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts b/src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts similarity index 100% rename from src/plugins/vis_type_vislib/public/sample_vis.test.mocks.ts rename to src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts diff --git a/src/plugins/vis_type_xy/public/services.ts b/src/plugins/vis_type_xy/public/services.ts index 086cab8fb217a..67d38d6647a98 100644 --- a/src/plugins/vis_type_xy/public/services.ts +++ b/src/plugins/vis_type_xy/public/services.ts @@ -43,9 +43,9 @@ export const [getThemeService, setThemeService] = createGetterSetter('xy charts.color'); +export const [getPalettesService, setPalettesService] = createGetterSetter< + ChartsPluginSetup['palettes'] +>('xy charts.palette'); export const [getDocLinks, setDocLinks] = createGetterSetter('DocLinks'); diff --git a/src/plugins/vis_type_xy/public/to_ast.test.ts b/src/plugins/vis_type_xy/public/to_ast.test.ts index 678a9faaec585..b6dedd694eb95 100644 --- a/src/plugins/vis_type_xy/public/to_ast.test.ts +++ b/src/plugins/vis_type_xy/public/to_ast.test.ts @@ -19,7 +19,7 @@ import { Vis } from '../../visualizations/public'; import { buildExpression } from '../../expressions/public'; -import { sampleAreaVis } from '../../vis_type_vislib/public/sample_vis.test.mocks'; +import { sampleAreaVis } from './sample_vis.test.mocks'; import { toExpressionAst } from './to_ast'; import { VisParams } from './types'; diff --git a/src/plugins/vis_type_xy/public/types/param.ts b/src/plugins/vis_type_xy/public/types/param.ts index c8cd020dec03c..69b5fe6158bd7 100644 --- a/src/plugins/vis_type_xy/public/types/param.ts +++ b/src/plugins/vis_type_xy/public/types/param.ts @@ -18,7 +18,7 @@ */ import { Fit, Position } from '@elastic/charts'; -import { Style, Labels } from '../../../charts/public'; +import { Style, Labels, PaletteOutput } from '../../../charts/public'; import { SchemaConfig } from '../../../visualizations/public'; import { ChartType } from '../../common'; @@ -156,5 +156,6 @@ export interface VisParams { * Add for detailed tooltip option */ detailedTooltip?: boolean; + palette: PaletteOutput; fittingFunction?: Exclude; } diff --git a/src/plugins/vis_type_xy/public/utils/domain.ts b/src/plugins/vis_type_xy/public/utils/domain.ts index 132c8df71428b..b5e3c15a42c43 100644 --- a/src/plugins/vis_type_xy/public/utils/domain.ts +++ b/src/plugins/vis_type_xy/public/utils/domain.ts @@ -52,7 +52,7 @@ export const getAdjustedDomain = ( data: Datatable['rows'], { accessor, params }: Aspect, timeZone: string, - domain?: DomainRange, + domain: DomainRange | undefined, hasBars?: boolean ): DomainRange => { if ( diff --git a/src/plugins/vis_type_xy/public/utils/get_all_series.test.ts b/src/plugins/vis_type_xy/public/utils/get_all_series.test.ts new file mode 100644 index 0000000000000..0f4f8fd297343 --- /dev/null +++ b/src/plugins/vis_type_xy/public/utils/get_all_series.test.ts @@ -0,0 +1,193 @@ +/* + * 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 { getAllSeries } from './get_all_series'; + +const rowsNoSplitSeries = [ + { + 'col-0-4': 'Kibana Airlines', + 'col-1-1': 85, + }, + { + 'col-0-4': 'ES-Air', + 'col-1-1': 84, + }, + { + 'col-0-4': 'Logstash Airways', + 'col-1-1': 82, + }, + { + 'col-0-4': 'JetBeats', + 'col-1-1': 81, + }, +]; + +const rowsWithSplitSeries = [ + { + 'col-0-4': 'ES-Air', + 'col-1-5': 0, + 'col-2-1': 71, + }, + { + 'col-0-4': 'ES-Air', + 'col-1-5': 1, + 'col-2-1': 14, + }, + { + 'col-0-4': 'Kibana Airlines', + 'col-1-5': 0, + 'col-2-1': 71, + }, + { + 'col-0-4': 'Kibana Airlines', + 'col-1-5': 1, + 'col-2-1': 13, + }, + { + 'col-0-4': 'JetBeats', + 'col-1-5': 0, + 'col-2-1': 72, + }, + { + 'col-0-4': 'JetBeats', + 'col-1-5': 1, + 'col-2-1': 9, + }, + { + 'col-0-4': 'Logstash Airways', + 'col-1-5': 0, + 'col-2-1': 71, + }, + { + 'col-0-4': 'Logstash Airways', + 'col-1-5': 1, + 'col-2-1': 10, + }, +]; + +const yAspects = [ + { + accessor: 'col-2-1', + column: 2, + title: 'Count', + format: { + id: 'number', + }, + aggType: 'count', + aggId: '1', + params: {}, + }, +]; + +const myltipleYAspects = [ + { + accessor: 'col-2-1', + column: 2, + title: 'Count', + format: { + id: 'number', + }, + aggType: 'count', + aggId: '1', + params: {}, + }, + { + accessor: 'col-3-4', + column: 3, + title: 'Average AvgTicketPrice', + format: { + id: 'number', + params: { + pattern: '$0,0.[00]', + }, + }, + aggType: 'avg', + aggId: '4', + params: {}, + }, +]; + +describe('getFilterClickData', () => { + it('returns empty array if splitAccessors is undefined', () => { + const splitAccessors = undefined; + const series = getAllSeries(rowsNoSplitSeries, splitAccessors, yAspects); + expect(series).toStrictEqual([]); + }); + + it('returns an array of series names if splitAccessors is an array', () => { + const splitAccessors = [ + { + accessor: 'col-1-5', + }, + ]; + const series = getAllSeries(rowsWithSplitSeries, splitAccessors, yAspects); + expect(series).toStrictEqual([0, 1]); + }); + + it('returns the correct array of series names for two splitAccessors without duplicates', () => { + const splitAccessors = [ + { + accessor: 'col-0-4', + }, + { + accessor: 'col-1-5', + }, + ]; + const series = getAllSeries(rowsWithSplitSeries, splitAccessors, yAspects); + expect(series).toStrictEqual([ + 'ES-Air - 0', + 'ES-Air - 1', + 'Kibana Airlines - 0', + 'Kibana Airlines - 1', + 'JetBeats - 0', + 'JetBeats - 1', + 'Logstash Airways - 0', + 'Logstash Airways - 1', + ]); + }); + + it('returns the correct array of series names for two splitAccessors and two y axis', () => { + const splitAccessors = [ + { + accessor: 'col-0-4', + }, + { + accessor: 'col-1-5', + }, + ]; + const series = getAllSeries(rowsWithSplitSeries, splitAccessors, myltipleYAspects); + expect(series).toStrictEqual([ + 'ES-Air - 0: Count', + 'ES-Air - 0: Average AvgTicketPrice', + 'ES-Air - 1: Count', + 'ES-Air - 1: Average AvgTicketPrice', + 'Kibana Airlines - 0: Count', + 'Kibana Airlines - 0: Average AvgTicketPrice', + 'Kibana Airlines - 1: Count', + 'Kibana Airlines - 1: Average AvgTicketPrice', + 'JetBeats - 0: Count', + 'JetBeats - 0: Average AvgTicketPrice', + 'JetBeats - 1: Count', + 'JetBeats - 1: Average AvgTicketPrice', + 'Logstash Airways - 0: Count', + 'Logstash Airways - 0: Average AvgTicketPrice', + 'Logstash Airways - 1: Count', + 'Logstash Airways - 1: Average AvgTicketPrice', + ]); + }); +}); diff --git a/src/plugins/vis_type_xy/public/utils/get_all_series.ts b/src/plugins/vis_type_xy/public/utils/get_all_series.ts new file mode 100644 index 0000000000000..8ffc59846c1fc --- /dev/null +++ b/src/plugins/vis_type_xy/public/utils/get_all_series.ts @@ -0,0 +1,62 @@ +/* + * 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 { TickFormatter } from '@elastic/charts'; +import { DatatableRow } from '../../../expressions/public'; +import { Column, Aspect } from '../types'; + +interface SplitAccessors { + accessor: Column['id']; + formatter?: TickFormatter; +} + +export const getAllSeries = ( + rows: DatatableRow[], + splitAccessors: SplitAccessors[] | undefined, + yAspects: Aspect[] +) => { + const allSeries: string[] = []; + if (!splitAccessors) return []; + + rows.forEach((row) => { + let seriesName = ''; + splitAccessors?.forEach(({ accessor, formatter }) => { + if (!accessor) return; + const name = formatter ? formatter(row[accessor]) : row[accessor]; + if (seriesName) { + seriesName += ` - ${name}`; + } else { + seriesName = name; + } + }); + + // multiple y axis + if (yAspects.length > 1) { + yAspects.forEach((aspect) => { + if (!allSeries.includes(`${seriesName}: ${aspect.title}`)) { + allSeries.push(`${seriesName}: ${aspect.title}`); + } + }); + } else { + if (!allSeries.includes(seriesName)) { + allSeries.push(seriesName); + } + } + }); + return allSeries; +}; diff --git a/src/plugins/vis_type_xy/public/utils/index.tsx b/src/plugins/vis_type_xy/public/utils/index.tsx index 20b5d7a3c8881..9143a57454d13 100644 --- a/src/plugins/vis_type_xy/public/utils/index.tsx +++ b/src/plugins/vis_type_xy/public/utils/index.tsx @@ -24,3 +24,4 @@ export { getSeriesNameFn } from './get_series_name_fn'; export { getXDomain, getAdjustedDomain } from './domain'; export { useColorPicker } from './use_color_picker'; export { getXAccessor } from './accessors'; +export { getAllSeries } from './get_all_series'; diff --git a/src/plugins/vis_type_xy/public/utils/use_color_picker.tsx b/src/plugins/vis_type_xy/public/utils/use_color_picker.tsx index 05de38b7700a9..666dcee29fc9d 100644 --- a/src/plugins/vis_type_xy/public/utils/use_color_picker.tsx +++ b/src/plugins/vis_type_xy/public/utils/use_color_picker.tsx @@ -17,10 +17,10 @@ * under the License. */ -import React, { BaseSyntheticEvent, useMemo } from 'react'; +import React, { BaseSyntheticEvent, useCallback, useMemo } from 'react'; import { LegendColorPicker, Position, XYChartSeriesIdentifier, SeriesName } from '@elastic/charts'; -import { PopoverAnchorPosition, EuiWrappingPopover } from '@elastic/eui'; +import { PopoverAnchorPosition, EuiWrappingPopover, EuiOutsideClickDetector } from '@elastic/eui'; import { ColorPicker } from '../../../charts/public'; @@ -61,18 +61,26 @@ export const useColorPicker = ( onClose(); }; + // rule doesn't know this is inside a functional component + // eslint-disable-next-line react-hooks/rules-of-hooks + const handleOutsideClick = useCallback(() => { + onClose?.(); + }, [onClose]); + return ( - - - + + + + + ); }, [getSeriesName, legendPosition, setColor] diff --git a/src/plugins/vis_type_xy/public/vis_component.tsx b/src/plugins/vis_type_xy/public/vis_component.tsx index dcf9f69cc291d..8d27d0161785a 100644 --- a/src/plugins/vis_type_xy/public/vis_component.tsx +++ b/src/plugins/vis_type_xy/public/vis_component.tsx @@ -48,6 +48,7 @@ import { LegendToggle, getBrushFromChartBrushEventFn, ClickTriggerEvent, + PaletteRegistry, } from '../../charts/public'; import { Datatable, IInterpreterRenderHandlers } from '../../expressions/public'; import type { PersistedState } from '../../visualizations/public'; @@ -62,10 +63,11 @@ import { getLegendActions, useColorPicker, getXAccessor, + getAllSeries, } from './utils'; import { XYAxis, XYEndzones, XYCurrentTime, XYSettings, XYThresholdLine } from './components'; import { getConfig } from './config'; -import { getThemeService, getColorsService, getDataActions } from './services'; +import { getThemeService, getDataActions, getPalettesService } from './services'; import { ChartType } from '../common'; import './_chart.scss'; @@ -81,22 +83,19 @@ export interface VisComponentProps { uiState: PersistedState; fireEvent: IInterpreterRenderHandlers['event']; renderComplete: IInterpreterRenderHandlers['done']; + syncColors: boolean; } export type VisComponentType = typeof VisComponent; const VisComponent = (props: VisComponentProps) => { - /** - * Stores all series labels to replicate vislib color map lookup - */ - const allSeries: Array = useMemo(() => [], []); const [showLegend, setShowLegend] = useState(() => { // TODO: Check when this bwc can safely be removed const bwcLegendStateDefault = props.visParams.addLegend == null ? true : props.visParams.addLegend; return props.uiState?.get('vis.legendOpen', bwcLegendStateDefault) as boolean; }); - + const [palettesRegistry, setPalettesRegistry] = useState(null); useEffect(() => { const fn = () => { props?.uiState?.emit?.('reload'); @@ -117,6 +116,14 @@ const VisComponent = (props: VisComponentProps) => { [props] ); + useEffect(() => { + const fetchPalettes = async () => { + const palettes = await getPalettesService().getPalettes(); + setPalettesRegistry(palettes); + }; + fetchPalettes(); + }, []); + const handleFilterClick = useCallback( ( visData: Datatable, @@ -225,7 +232,8 @@ const VisComponent = (props: VisComponentProps) => { [props.uiState] ); - const { visData, visParams } = props; + const { visData, visParams, syncColors } = props; + const config = getConfig(visData, visParams); const timeZone = getTimeZone(); const xDomain = @@ -245,21 +253,58 @@ const VisComponent = (props: VisComponentProps) => { const isDarkMode = getThemeService().useDarkMode(); const getSeriesName = getSeriesNameFn(config.aspects, config.aspects.y.length > 1); + const splitAccessors = config.aspects.series?.map(({ accessor, formatter }) => { + return { accessor, formatter }; + }); + + const allSeries = useMemo(() => getAllSeries(visData.rows, splitAccessors, config.aspects.y), [ + config.aspects.y, + splitAccessors, + visData.rows, + ]); + const getSeriesColor = useCallback( (series: XYChartSeriesIdentifier) => { - const seriesName = getSeriesName(series); + const seriesName = getSeriesName(series) as string; if (!seriesName) { - return; + return null; } - const overwriteColors: Record = props.uiState?.get ? props.uiState.get('vis.colors', {}) : {}; - allSeries.push(seriesName); - return getColorsService().createColorLookupFunction(allSeries, overwriteColors)(seriesName); + if (Object.keys(overwriteColors).includes(seriesName)) { + return overwriteColors[seriesName]; + } + const outputColor = palettesRegistry?.get(visParams.palette.name).getColor( + [ + { + name: seriesName, + rankAtDepth: splitAccessors + ? allSeries.findIndex((name) => name === seriesName) + : config.aspects.y.findIndex((aspect) => aspect.accessor === series.yAccessor), + totalSeriesAtDepth: splitAccessors ? allSeries.length : config.aspects.y.length, + }, + ], + { + maxDepth: 1, + totalSeries: splitAccessors ? allSeries.length : config.aspects.y.length, + behindText: false, + syncColors, + } + ); + return outputColor || null; }, - [allSeries, getSeriesName, props.uiState] + [ + allSeries, + config.aspects.y, + getSeriesName, + props.uiState, + splitAccessors, + syncColors, + visParams.palette.name, + palettesRegistry, + ] ); const xAccessor = getXAccessor(config.aspects.x); const splitSeriesAccessors = config.aspects.series diff --git a/src/plugins/vis_type_xy/public/vis_renderer.tsx b/src/plugins/vis_type_xy/public/vis_renderer.tsx index 16463abb07631..ee0c9983435e9 100644 --- a/src/plugins/vis_type_xy/public/vis_renderer.tsx +++ b/src/plugins/vis_type_xy/public/vis_renderer.tsx @@ -45,9 +45,9 @@ export const xyVisRenderer: ExpressionRenderDefinition = { name: visName, displayName: 'XY visualization', reuseDomNode: true, - render: (domNode, { visData, visConfig, visType }, handlers) => { + render: async (domNode, { visData, visConfig, visType, syncColors }, handlers) => { const showNoResult = shouldShowNoResultsMessage(visData, visType); - const isSplitChart = Boolean(visConfig.dimensions.splitRow || visConfig.dimensions.splitRow); + const isSplitChart = Boolean(visConfig.dimensions.splitRow); handlers.onDestroy(() => unmountComponentAtNode(domNode)); render( @@ -61,6 +61,7 @@ export const xyVisRenderer: ExpressionRenderDefinition = { renderComplete={handlers.done} fireEvent={handlers.event} uiState={handlers.uiState as PersistedState} + syncColors={syncColors} /> diff --git a/src/plugins/vis_type_xy/public/vis_types/area.tsx b/src/plugins/vis_type_xy/public/vis_types/area.tsx index 58423d2f619fa..f04105470e01d 100644 --- a/src/plugins/vis_type_xy/public/vis_types/area.tsx +++ b/src/plugins/vis_type_xy/public/vis_types/area.tsx @@ -119,6 +119,10 @@ export const getAreaVisTypeDefinition = ( ], addTooltip: true, detailedTooltip: true, + palette: { + type: 'palette', + name: 'default', + }, addLegend: true, legendPosition: Position.Right, fittingFunction: Fit.Linear, diff --git a/src/plugins/vis_type_xy/public/vis_types/histogram.tsx b/src/plugins/vis_type_xy/public/vis_types/histogram.tsx index 5bc5f1b49e5da..9e032b34c98de 100644 --- a/src/plugins/vis_type_xy/public/vis_types/histogram.tsx +++ b/src/plugins/vis_type_xy/public/vis_types/histogram.tsx @@ -122,6 +122,10 @@ export const getHistogramVisTypeDefinition = ( radiusRatio: 0, addTooltip: true, detailedTooltip: true, + palette: { + type: 'palette', + name: 'default', + }, addLegend: true, legendPosition: Position.Right, times: [], diff --git a/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.tsx b/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.tsx index 3029b3dcd6765..4b1e95368d9fc 100644 --- a/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.tsx +++ b/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.tsx @@ -122,6 +122,10 @@ export const getHorizontalBarVisTypeDefinition = ( ], addTooltip: true, detailedTooltip: true, + palette: { + type: 'palette', + name: 'default', + }, addLegend: true, legendPosition: Position.Right, times: [], diff --git a/src/plugins/vis_type_xy/public/vis_types/line.tsx b/src/plugins/vis_type_xy/public/vis_types/line.tsx index e0f83ce649d23..e146b91a6141b 100644 --- a/src/plugins/vis_type_xy/public/vis_types/line.tsx +++ b/src/plugins/vis_type_xy/public/vis_types/line.tsx @@ -119,6 +119,10 @@ export const getLineVisTypeDefinition = ( ], addTooltip: true, detailedTooltip: true, + palette: { + type: 'palette', + name: 'default', + }, addLegend: true, legendPosition: Position.Right, fittingFunction: Fit.Linear, diff --git a/src/plugins/vis_type_xy/public/xy_vis_fn.ts b/src/plugins/vis_type_xy/public/xy_vis_fn.ts index 47c4caf243b36..f24b7391c1391 100644 --- a/src/plugins/vis_type_xy/public/xy_vis_fn.ts +++ b/src/plugins/vis_type_xy/public/xy_vis_fn.ts @@ -34,6 +34,7 @@ export interface RenderValue { visData: Datatable; visType: ChartType; visConfig: VisParams; + syncColors: boolean; } export type VisTypeXyExpressionFunctionDefinition = ExpressionFunctionDefinition< @@ -80,6 +81,7 @@ export const createVisTypeXyVisFn = (): VisTypeXyExpressionFunctionDefinition => visType, visConfig, visData: context, + syncColors: handlers?.isSyncColorsEnabled?.() ?? false, }, }; }, diff --git a/src/plugins/vis_type_xy/tsconfig.json b/src/plugins/vis_type_xy/tsconfig.json new file mode 100644 index 0000000000000..5cb0bc8d0bc8e --- /dev/null +++ b/src/plugins/vis_type_xy/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../vis_default_editor/tsconfig.json" }, + ] +} diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 3956f930758d7..4eaf70c98a26e 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -102,13 +102,13 @@ export class VisualizeEmbeddable private query?: Query; private filters?: Filter[]; private searchSessionId?: string; + private syncColors?: boolean; private visCustomizations?: Pick; private subscriptions: Subscription[] = []; private expression: string = ''; private vis: Vis; private domNode: any; public readonly type = VISUALIZE_EMBEDDABLE_TYPE; - private autoRefreshFetchSubscription: Subscription; private abortController?: AbortController; private readonly deps: VisualizeEmbeddableFactoryDeps; private readonly inspectorAdapters?: Adapters; @@ -146,16 +146,13 @@ export class VisualizeEmbeddable ); this.deps = deps; this.timefilter = timefilter; + this.syncColors = this.input.syncColors; this.vis = vis; this.vis.uiState.on('change', this.uiStateChangeHandler); this.vis.uiState.on('reload', this.reload); this.attributeService = attributeService; this.savedVisualizationsLoader = savedVisualizationsLoader; - this.autoRefreshFetchSubscription = timefilter - .getAutoRefreshFetch$() - .subscribe(this.updateHandler.bind(this)); - this.subscriptions.push( this.getUpdated$().subscribe(() => { const isDirty = this.handleChanges(); @@ -253,6 +250,11 @@ export class VisualizeEmbeddable dirty = true; } + if (this.syncColors !== this.input.syncColors) { + this.syncColors = this.input.syncColors; + dirty = true; + } + if (this.vis.description && this.domNode) { this.domNode.setAttribute('data-description', this.vis.description); } @@ -368,7 +370,6 @@ export class VisualizeEmbeddable this.handler.destroy(); this.handler.getElement().remove(); } - this.autoRefreshFetchSubscription.unsubscribe(); } public reload = () => { @@ -383,6 +384,7 @@ export class VisualizeEmbeddable filters: this.input.filters, }, searchSessionId: this.input.searchSessionId, + syncColors: this.input.syncColors, uiState: this.vis.uiState, inspectorAdapters: this.inspectorAdapters, }; diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 80bf145e2a9f5..94519dceb3014 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -197,6 +197,7 @@ export class VisualizeEmbeddableFactory const saveOptions = { confirmOverwrite: false, returnToOrigin: true, + isTitleDuplicateConfirmed: true, }; savedVis.title = title; savedVis.copyOnSave = false; diff --git a/src/plugins/visualizations/public/legacy/vis_update_state.d.ts b/src/plugins/visualizations/public/legacy/vis_update_state.d.ts new file mode 100644 index 0000000000000..a400ac3d1500f --- /dev/null +++ b/src/plugins/visualizations/public/legacy/vis_update_state.d.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 { SavedVisState } from '../types'; + +declare function updateOldState(oldState: unknown): SavedVisState; + +export { updateOldState }; diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 2088f52428aa7..223fe1a852f57 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -27,7 +27,6 @@ interface CommonBaseVisTypeOptions extends Pick< VisType, | 'description' - | 'editor' | 'getInfoMessage' | 'getSupportedTriggers' | 'hierarchicalData' @@ -91,7 +90,6 @@ export class BaseVisType implements VisType public readonly options; public readonly visualization; public readonly visConfig; - public readonly editor; public readonly editorConfig; public hidden; public readonly requestHandler; @@ -119,7 +117,6 @@ export class BaseVisType implements VisType this.image = opts.image; this.visualization = opts.visualization; this.visConfig = defaultsDeep({}, opts.visConfig, { defaults: {} }); - this.editor = opts.editor; this.editorConfig = defaultsDeep({}, opts.editorConfig, { collections: {} }); this.options = defaultsDeep({}, opts.options, defaultOptions); this.stage = opts.stage ?? 'production'; diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index 88a4dad106897..6ac798554fceb 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -16,11 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - import { IconType } from '@elastic/eui'; import React, { ReactNode } from 'react'; import { Adapters } from 'src/plugins/inspector'; -import { VisEditorConstructor } from 'src/plugins/visualize/public'; import { IndexPattern, AggGroupNames, AggParam, AggGroupName } from '../../../data/public'; import { Vis, VisParams, VisToExpressionAst, VisualizationControllerConstructor } from '../types'; @@ -141,13 +139,6 @@ export interface VisType { readonly options: VisTypeOptions; - /** - * The editor that should be used to edit visualizations of this type. - * If this is not specified the default visualize editor will be used (and should be configured via schemas) - * and editorConfig. - */ - readonly editor?: VisEditorConstructor; - // TODO: The following types still need to be refined properly. readonly editorConfig: Record; readonly visConfig: Record; diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts index d3fc5de93c366..4f1b7b3a163be 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts @@ -1720,6 +1720,13 @@ describe('migration visualization', () => { expect(isVislibVis).toEqual(true); }); + it('should decorate existing docs with the kibana legacy palette', () => { + const migratedTestDoc = migrate(getTestDoc()); + const { palette } = JSON.parse(migratedTestDoc.attributes.visState).params; + + expect(palette.name).toEqual('kibana_palette'); + }); + describe('labels.filter', () => { it('should keep existing categoryAxes labels.filter value', () => { const migratedTestDoc = migrate(getTestDoc('area', [{ labels: { filter: false } }])); diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts index c625662ab7fe3..8317536f4b28a 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts @@ -21,7 +21,6 @@ import { cloneDeep, get, omit, has, flow } from 'lodash'; import { SavedObjectMigrationFn } from 'kibana/server'; -import { ChartType } from '../../../vis_type_xy/common'; import { DEFAULT_QUERY_LANGUAGE } from '../../../data/common'; const migrateIndexPattern: SavedObjectMigrationFn = (doc) => { @@ -804,6 +803,11 @@ const decorateAxes = ( }, })); +// Inlined from vis_type_xy +const CHART_TYPE_AREA = 'area'; +const CHART_TYPE_LINE = 'line'; +const CHART_TYPE_HISTOGRAM = 'histogram'; + /** * Migrate vislib bar, line and area charts to use new vis_type_xy plugin */ @@ -819,11 +823,11 @@ const migrateVislibAreaLineBarTypes: SavedObjectMigrationFn = (doc) => } if ( visState && - [ChartType.Area, ChartType.Line, ChartType.Histogram].includes(visState?.params?.type) + [CHART_TYPE_AREA, CHART_TYPE_LINE, CHART_TYPE_HISTOGRAM].includes(visState?.params?.type) ) { const isHorizontalBar = visState.type === 'horizontal_bar'; const isLineOrArea = - visState?.params?.type === ChartType.Area || visState?.params?.type === ChartType.Line; + visState?.params?.type === CHART_TYPE_AREA || visState?.params?.type === CHART_TYPE_LINE; return { ...doc, attributes: { @@ -832,6 +836,10 @@ const migrateVislibAreaLineBarTypes: SavedObjectMigrationFn = (doc) => ...visState, params: { ...visState.params, + palette: { + type: 'palette', + name: 'kibana_palette', + }, categoryAxes: visState.params.categoryAxes && decorateAxes(visState.params.categoryAxes, !isHorizontalBar), diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json new file mode 100644 index 0000000000000..d7c5e6a4b4366 --- /dev/null +++ b/src/plugins/visualizations/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../dashboard/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" }, + { "path": "../ui_actions/tsconfig.json" }, + { "path": "../embeddable/tsconfig.json" }, + { "path": "../inspector/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + { "path": "../saved_objects_tagging_oss/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../discover/tsconfig.json" }, + ] +} diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx index 627d5cd00147b..becabc60eff16 100644 --- a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -190,6 +190,17 @@ const TopNav = ({ } }, [vis.params, vis.type, services.data.indexPatterns, vis.data.indexPattern]); + useEffect(() => { + const autoRefreshFetchSub = services.data.query.timefilter.timefilter + .getAutoRefreshFetch$() + .subscribe(() => { + visInstance.embeddableHandler.reload(); + }); + return () => { + autoRefreshFetchSub.unsubscribe(); + }; + }, [services.data.query.timefilter.timefilter, visInstance.embeddableHandler]); + return isChromeVisible ? ( /** * Most visualizations have all search bar components enabled. diff --git a/src/plugins/visualize/public/application/types.ts b/src/plugins/visualize/public/application/types.ts index 1729d273e24bc..a36ff852f5731 100644 --- a/src/plugins/visualize/public/application/types.ts +++ b/src/plugins/visualize/public/application/types.ts @@ -18,14 +18,14 @@ */ import { History } from 'history'; -import { TimeRange, Query, Filter, DataPublicPluginStart } from 'src/plugins/data/public'; +import { Query, Filter, DataPublicPluginStart, TimeRange } from 'src/plugins/data/public'; import { - PersistedState, SavedVisState, VisualizationsStart, Vis, VisualizeEmbeddableContract, VisSavedObject, + PersistedState, } from 'src/plugins/visualizations/public'; import { CoreStart, @@ -80,20 +80,6 @@ export type VisualizeAppStateContainer = ReduxLikeStateContainer< VisualizeAppStateTransitions >; -export interface EditorRenderProps { - core: CoreStart; - data: DataPublicPluginStart; - filters: Filter[]; - timeRange: TimeRange; - query?: Query; - savedSearch?: SavedObject; - uiState: PersistedState; - /** - * Flag to determine if visualiztion is linked to the saved search - */ - linked: boolean; -} - export interface VisualizeServices extends CoreStart { stateTransferService: EmbeddableStateTransfer; embeddable: EmbeddableStart; @@ -147,3 +133,17 @@ export interface IEditorController { render(props: EditorRenderProps): Promise | void; destroy(): void; } + +export interface EditorRenderProps { + core: CoreStart; + data: DataPublicPluginStart; + filters: Filter[]; + timeRange: TimeRange; + query?: Query; + savedSearch?: SavedObject; + uiState: PersistedState; + /** + * Flag to determine if visualiztion is linked to the saved search + */ + linked: boolean; +} diff --git a/src/plugins/visualize/public/application/utils/use/use_editor_updates.test.ts b/src/plugins/visualize/public/application/utils/use/use_editor_updates.test.ts index 23894368d606c..414489eaced9c 100644 --- a/src/plugins/visualize/public/application/utils/use/use_editor_updates.test.ts +++ b/src/plugins/visualize/public/application/utils/use/use_editor_updates.test.ts @@ -21,12 +21,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { EventEmitter } from 'events'; import { useEditorUpdates } from './use_editor_updates'; -import { - VisualizeServices, - VisualizeAppStateContainer, - SavedVisInstance, - IEditorController, -} from '../../types'; +import { VisualizeServices, VisualizeAppStateContainer, SavedVisInstance } from '../../types'; +import type { IEditorController } from '../../types'; import { visualizeAppStateStub } from '../stubs'; import { createVisualizeServicesMock } from '../mocks'; diff --git a/src/plugins/visualize/public/application/utils/use/use_editor_updates.ts b/src/plugins/visualize/public/application/utils/use/use_editor_updates.ts index c29f6337a6246..9fdcbe1571893 100644 --- a/src/plugins/visualize/public/application/utils/use/use_editor_updates.ts +++ b/src/plugins/visualize/public/application/utils/use/use_editor_updates.ts @@ -25,8 +25,8 @@ import { VisualizeServices, VisualizeAppState, VisualizeAppStateContainer, - IEditorController, VisualizeEditorVisInstance, + IEditorController, } from '../../types'; export const useEditorUpdates = ( diff --git a/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.test.ts b/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.test.ts index 48afc9d468204..fe052f4ca133e 100644 --- a/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.test.ts +++ b/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.test.ts @@ -26,7 +26,8 @@ import { redirectWhenMissing } from '../../../../../kibana_utils/public'; import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs'; import { VisualizeServices } from '../../types'; import { VisualizeConstants } from '../../visualize_constants'; -import { setDefaultEditor } from '../../../services'; +import { setVisEditorsRegistry } from '../../../services'; +import { createVisEditorsRegistry } from '../../../vis_editors_registry'; import { createEmbeddableStateTransferMock } from '../../../../../embeddable/public/mocks'; const mockDefaultEditorControllerDestroy = jest.fn(); @@ -75,10 +76,14 @@ describe('useSavedVisInstance', () => { const eventEmitter = new EventEmitter(); beforeEach(() => { - setDefaultEditor( + const registry = createVisEditorsRegistry(); + + registry.registerDefault( jest.fn().mockImplementation(() => ({ destroy: mockDefaultEditorControllerDestroy })) ); + setVisEditorsRegistry(registry); + mockServices = ({ ...coreStartMock, toastNotifications, diff --git a/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.ts b/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.ts index 3f9b3ca9b8b73..6e5b3a012aabd 100644 --- a/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.ts +++ b/src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.ts @@ -26,9 +26,9 @@ import { redirectWhenMissing } from '../../../../../kibana_utils/public'; import { getVisualizationInstance } from '../get_visualization_instance'; import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs'; -import { SavedVisInstance, IEditorController, VisualizeServices } from '../../types'; +import { SavedVisInstance, VisualizeServices, IEditorController } from '../../types'; import { VisualizeConstants } from '../../visualize_constants'; -import { getDefaultEditor } from '../../../services'; +import { getVisEditorsRegistry } from '../../../services'; /** * This effect is responsible for instantiating a saved vis or creating a new one @@ -122,13 +122,16 @@ export const useSavedVisInstance = ( // do not create editor in embeded mode if (visEditorRef.current) { if (isChromeVisible) { - const Editor = vis.type.editor || getDefaultEditor(); - visEditorController = new Editor( - visEditorRef.current, - vis, - eventEmitter, - embeddableHandler - ); + const Editor = getVisEditorsRegistry().get(vis.type.editorConfig?.editor); + + if (Editor) { + visEditorController = new Editor( + visEditorRef.current, + vis, + eventEmitter, + embeddableHandler + ); + } } else { embeddableHandler.render(visEditorRef.current); } diff --git a/src/plugins/visualize/public/application/utils/use/use_vis_byvalue.ts b/src/plugins/visualize/public/application/utils/use/use_vis_byvalue.ts index 9e222d208f460..45f31d57736a9 100644 --- a/src/plugins/visualize/public/application/utils/use/use_vis_byvalue.ts +++ b/src/plugins/visualize/public/application/utils/use/use_vis_byvalue.ts @@ -20,10 +20,10 @@ import { EventEmitter } from 'events'; import { useEffect, useRef, useState } from 'react'; import { VisualizeInput } from 'src/plugins/visualizations/public'; -import { ByValueVisInstance, IEditorController, VisualizeServices } from '../../types'; +import { ByValueVisInstance, VisualizeServices, IEditorController } from '../../types'; import { getVisualizationInstanceFromInput } from '../get_visualization_instance'; import { getEditBreadcrumbs } from '../breadcrumbs'; -import { getDefaultEditor } from '../../../services'; +import { getVisEditorsRegistry } from '../../../services'; export const useVisByValue = ( services: VisualizeServices, @@ -50,14 +50,18 @@ export const useVisByValue = ( } const byValueVisInstance = await getVisualizationInstanceFromInput(services, valueInput); const { embeddableHandler, vis } = byValueVisInstance; + let visEditorController; - const Editor = vis.type.editor || getDefaultEditor(); - const visEditorController = new Editor( - visEditorRef.current, - vis, - eventEmitter, - embeddableHandler - ); + const Editor = getVisEditorsRegistry().get(vis.type.editorConfig?.editor); + + if (Editor) { + visEditorController = new Editor( + visEditorRef.current, + vis, + eventEmitter, + embeddableHandler + ); + } const originatingAppName = originatingApp ? stateTransferService.getAppNameFromId(originatingApp) diff --git a/src/plugins/visualize/public/index.ts b/src/plugins/visualize/public/index.ts index c9ac85c5123ce..b749e7288f59f 100644 --- a/src/plugins/visualize/public/index.ts +++ b/src/plugins/visualize/public/index.ts @@ -20,13 +20,10 @@ import { PluginInitializerContext } from 'kibana/public'; import { VisualizePlugin, VisualizePluginSetup } from './plugin'; -export type { - EditorRenderProps, - IEditorController, - VisEditorConstructor, -} from './application/types'; export { VisualizeConstants } from './application/visualize_constants'; +export { IEditorController, EditorRenderProps } from './application/types'; + export { VisualizePluginSetup }; export const plugin = (context: PluginInitializerContext) => { diff --git a/src/plugins/visualize/public/plugin.ts b/src/plugins/visualize/public/plugin.ts index 5eef58a336eab..75716ab43a6fc 100644 --- a/src/plugins/visualize/public/plugin.ts +++ b/src/plugins/visualize/public/plugin.ts @@ -44,7 +44,7 @@ import { UrlForwardingSetup, UrlForwardingStart } from '../../url_forwarding/pub import { VisualizationsStart } from '../../visualizations/public'; import { VisualizeConstants } from './application/visualize_constants'; import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public'; -import { VisEditorConstructor, VisualizeServices } from './application/types'; +import { VisualizeServices } from './application/types'; import { DEFAULT_APP_CATEGORIES } from '../../../core/public'; import { SavedObjectsStart } from '../../saved_objects/public'; import { EmbeddableStart } from '../../embeddable/public'; @@ -57,10 +57,11 @@ import { setIndexPatterns, setQueryService, setShareService, - setDefaultEditor, + setVisEditorsRegistry, } from './services'; import { visualizeFieldAction } from './actions/visualize_field_action'; import { createVisualizeUrlGenerator } from './url_generator'; +import { createVisEditorsRegistry, VisEditorsRegistry } from './vis_editors_registry'; export interface VisualizePluginStartDependencies { data: DataPublicPluginStart; @@ -83,7 +84,7 @@ export interface VisualizePluginSetupDependencies { } export interface VisualizePluginSetup { - setDefaultEditor: (editor: VisEditorConstructor) => void; + visEditorsRegistry: VisEditorsRegistry; } export class VisualizePlugin @@ -98,6 +99,8 @@ export class VisualizePlugin private stopUrlTracking: (() => void) | undefined = undefined; private currentHistory: ScopedHistory | undefined = undefined; + private readonly visEditorsRegistry = createVisEditorsRegistry(); + constructor(private initializerContext: PluginInitializerContext) {} public async setup( @@ -244,13 +247,12 @@ export class VisualizePlugin } return { - setDefaultEditor: (editor) => { - setDefaultEditor(editor); - }, + visEditorsRegistry: this.visEditorsRegistry, } as VisualizePluginSetup; } public start(core: CoreStart, plugins: VisualizePluginStartDependencies) { + setVisEditorsRegistry(this.visEditorsRegistry); setApplication(core.application); setIndexPatterns(plugins.data.indexPatterns); setQueryService(plugins.data.query); diff --git a/src/plugins/visualize/public/services.ts b/src/plugins/visualize/public/services.ts index 7994ad14543d5..5c5ab6072e494 100644 --- a/src/plugins/visualize/public/services.ts +++ b/src/plugins/visualize/public/services.ts @@ -21,7 +21,7 @@ import { ApplicationStart, IUiSettingsClient } from '../../../core/public'; import { createGetterSetter } from '../../../plugins/kibana_utils/public'; import { IndexPatternsContract, DataPublicPluginStart } from '../../../plugins/data/public'; import { SharePluginStart } from '../../../plugins/share/public'; -import { VisEditorConstructor } from './application/types'; +import { VisEditorsRegistry } from './vis_editors_registry'; export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); @@ -33,9 +33,10 @@ export const [getIndexPatterns, setIndexPatterns] = createGetterSetter( - 'DefaultEditor' -); +export const [ + getVisEditorsRegistry, + setVisEditorsRegistry, +] = createGetterSetter('VisEditorsRegistry'); export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] diff --git a/src/plugins/visualize/public/vis_editors_registry.ts b/src/plugins/visualize/public/vis_editors_registry.ts new file mode 100644 index 0000000000000..acab183bf8a0c --- /dev/null +++ b/src/plugins/visualize/public/vis_editors_registry.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { VisEditorConstructor } from './application/types'; + +const DEFAULT_NAME = 'default'; + +export const createVisEditorsRegistry = () => { + const map = new Map(); + + return { + registerDefault: (editor: VisEditorConstructor) => { + map.set(DEFAULT_NAME, editor); + }, + register: (name: string, editor: VisEditorConstructor) => { + if (name) { + map.set(name, editor); + } + }, + get: (name: string) => map.get(name || DEFAULT_NAME), + }; +}; + +export type VisEditorsRegistry = ReturnType; diff --git a/src/plugins/visualize/tsconfig.json b/src/plugins/visualize/tsconfig.json new file mode 100644 index 0000000000000..bc0891f391746 --- /dev/null +++ b/src/plugins/visualize/tsconfig.json @@ -0,0 +1,34 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../url_forwarding/tsconfig.json" }, + { "path": "../navigation/tsconfig.json" }, + { "path": "../saved_objects/tsconfig.json" }, + { "path": "../visualizations/tsconfig.json" }, + { "path": "../embeddable/tsconfig.json" }, + { "path": "../dashboard/tsconfig.json" }, + { "path": "../ui_actions/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../share/tsconfig.json" }, + { "path": "../saved_objects_tagging_oss/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../home/tsconfig.json" }, + { "path": "../presentation_util/tsconfig.json" }, + { "path": "../discover/tsconfig.json" }, + ] +} diff --git a/tasks/licenses_csv_report.js b/tasks/licenses_csv_report.js deleted file mode 100644 index f504cbcaa5fc8..0000000000000 --- a/tasks/licenses_csv_report.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { writeFileSync } from 'fs'; -import { resolve } from 'path'; -import { getInstalledPackages } from '../src/dev/npm'; -import { engines } from '../package'; -import { LICENSE_OVERRIDES } from '../src/dev/license_checker'; - -import { isNull, isUndefined } from 'lodash'; - -const allDoubleQuoteRE = /"/g; - -function escapeValue(value) { - if (isNull(value)) { - return; - } - - return `"${value.replace(allDoubleQuoteRE, '""')}"`; -} - -function formatCsvValues(fields, values) { - return fields - .map((field) => { - const value = values[field]; - - if (isNull(value) || isUndefined(value)) { - return null; - } - - return value.toString(); - }) - .map(escapeValue) - .join(','); -} - -export default function licensesCSVReport(grunt) { - grunt.registerTask('licenses:csv_report', 'Report of 3rd party dependencies', async function () { - const fields = ['name', 'version', 'url', 'license', 'sourceURL']; - const done = this.async(); - - try { - const file = grunt.option('csv'); - const directory = grunt.option('directory'); - const dev = Boolean(grunt.option('dev')); - - const packages = await getInstalledPackages({ - directory: directory ? resolve(directory) : grunt.config.get('root'), - licenseOverrides: LICENSE_OVERRIDES, - dev, - }); - - packages.unshift( - { - name: 'Node.js', - version: engines.node, - repository: 'https://nodejs.org', - licenses: ['MIT'], - }, - { - name: 'Red Hat Universal Base Image minimal', - version: '8', - repository: - 'https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/5c359a62bed8bd75a2c3fba8', - licenses: [ - 'Custom;https://www.redhat.com/licenses/EULA_Red_Hat_Universal_Base_Image_English_20190422.pdf', - ], - sourceURL: 'https://oss-dependencies.elastic.co/redhat/ubi/ubi-minimal-8-source.tar.gz', - } - ); - - const csv = packages - .map((pkg) => { - const data = { - name: pkg.name, - version: pkg.version, - url: pkg.repository || `https://www.npmjs.com/package/${pkg.name}`, - license: pkg.licenses.join(','), - sourceURL: pkg.sourceURL, - }; - - return formatCsvValues(fields, data); - }) - .join('\n'); - - if (file) { - writeFileSync(file, `${fields.join(',')}\n${csv}`); - grunt.log.writeln(`wrote to ${file}`); - } else { - grunt.log.writeln(csv); - grunt.log.writeln('\nspecify "--csv [filepath]" to write the data to a specific file'); - } - - done(); - } catch (err) { - grunt.fail.fatal(err); - done(err); - } - }); -} diff --git a/test/common/config.js b/test/common/config.js index 6c7d64e3e0bc0..6809b87bc807d 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -44,7 +44,14 @@ export default function () { '--logging.json=false', `--server.port=${kbnTestConfig.getPort()}`, '--status.allowAnonymous=true', - `--elasticsearch.hosts=${formatUrl(servers.elasticsearch)}`, + // We shouldn't embed credentials into the URL since Kibana requests to Elasticsearch should + // either include `kibanaServerTestUser` credentials, or credentials provided by the test + // user, or none at all in case anonymous access is used. + `--elasticsearch.hosts=${formatUrl( + Object.fromEntries( + Object.entries(servers.elasticsearch).filter(([key]) => key.toLowerCase() !== 'auth') + ) + )}`, `--elasticsearch.username=${kibanaServerTestUser.username}`, `--elasticsearch.password=${kibanaServerTestUser.password}`, `--home.disableWelcomeScreen=true`, diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index 6e524b2cd33df..fcd136a2720e4 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -34,7 +34,6 @@ GET _search export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); - const find = getService('find'); const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'console']); @@ -84,12 +83,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should resize the editor', async () => { - const editor = await find.byCssSelector('.conApp'); + const editor = await PageObjects.console.getEditor(); await browser.setWindowSize(1300, 1100); const initialSize = await editor.getSize(); await browser.setWindowSize(1000, 1100); const afterSize = await editor.getSize(); expect(initialSize.width).to.be.greaterThan(afterSize.width); }); + + it('should provide basic auto-complete functionality', async () => { + // Ensure that the text area can be interacted with + await PageObjects.console.dismissTutorial(); + expect(await PageObjects.console.hasAutocompleter()).to.be(false); + await PageObjects.console.promptAutocomplete(); + retry.waitFor('autocomplete to be visible', () => PageObjects.console.hasAutocompleter()); + }); }); } diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index f67a2722da367..5b0fcd0d331b5 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -17,12 +17,14 @@ * under the License. */ +import { Key } from 'selenium-webdriver'; import { FtrProviderContext } from '../ftr_provider_context'; import { WebElementWrapper } from '../services/lib/web_element_wrapper'; export function ConsolePageProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); + const find = getService('find'); class ConsolePage { public async getVisibleTextFromAceEditor(editor: WebElementWrapper) { @@ -79,6 +81,38 @@ export function ConsolePageProvider({ getService }: FtrProviderContext) { public async getRequestFontSize() { return await this.getFontSize(await this.getRequestEditor()); } + + public async getEditor() { + return testSubjects.find('console-application'); + } + + public async dismissTutorial() { + try { + const closeButton = await testSubjects.find('help-close-button'); + await closeButton.click(); + } catch (e) { + // Ignore because it is probably not there. + } + } + + public async promptAutocomplete() { + // This focusses the cursor on the bottom of the text area + const editor = await this.getEditor(); + const content = await editor.findByCssSelector('.ace_content'); + await content.click(); + const textArea = await testSubjects.find('console-textarea'); + // There should be autocomplete for this on all license levels + await textArea.pressKeys('\nGET s'); + await textArea.pressKeys([Key.CONTROL, Key.SPACE]); + } + + public async hasAutocompleter(): Promise { + try { + return Boolean(await find.byCssSelector('.ace_autocomplete')); + } catch (e) { + return false; + } + } } return new ConsolePage(); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 5b07cb0e534db..7541d9e5cf3d7 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -61,6 +61,9 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro let isPresent = false; await retry.try(async () => { isPresent = await testSubjects.exists(testSubj, { timeout: 20000 }); + if (!isPresent) { + isPresent = await testSubjects.exists('visNoResult', { timeout: 1000 }); + } }); if (!isPresent) { throw new Error(`TSVB ${name} tab is not loaded`); diff --git a/test/functional/services/dashboard/panel_actions.ts b/test/functional/services/dashboard/panel_actions.ts index 7e5ef068e2184..8ae7a6b50c111 100644 --- a/test/functional/services/dashboard/panel_actions.ts +++ b/test/functional/services/dashboard/panel_actions.ts @@ -33,6 +33,7 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft const log = getService('log'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['header', 'common']); + const inspector = getService('inspector'); return new (class DashboardPanelActions { async findContextMenu(parent?: WebElementWrapper) { @@ -163,6 +164,16 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft await this.openInspector(header); } + async getSearchSessionIdByTitle(title: string) { + await this.openInspectorByTitle(title); + await inspector.openInspectorRequestsView(); + const searchSessionId = await ( + await testSubjects.find('inspectorRequestSearchSessionId') + ).getAttribute('data-search-session-id'); + await inspector.close(); + return searchSessionId; + } + async openInspector(parent?: WebElementWrapper) { await this.openContextMenu(parent); const exists = await testSubjects.exists(OPEN_INSPECTOR_TEST_SUBJ); diff --git a/test/scripts/checks/mocha_coverage.sh b/test/scripts/checks/mocha_coverage.sh deleted file mode 100755 index e1afad0ab775f..0000000000000 --- a/test/scripts/checks/mocha_coverage.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -yarn nyc --reporter=html --reporter=json-summary --report-dir=./target/kibana-coverage/mocha node scripts/mocha diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 7384cec36b277..2edd66579f72f 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -44,8 +44,4 @@ else rename_coverage_file "oss-integration" echo "" echo "" - echo " -> Running mocha tests with coverage" - ./test/scripts/checks/mocha_coverage.sh - echo "" - echo "" fi diff --git a/test/tsconfig.json b/test/tsconfig.json index f9008505ed66e..684efc145e4d0 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -8,9 +8,16 @@ "exclude": ["plugin_functional/plugins/**/*", "interpreter_functional/plugins/**/*"], "references": [ { "path": "../src/core/tsconfig.json" }, + { "path": "../src/plugins/telemetry_management_section/tsconfig.json" }, + { "path": "../src/plugins/advanced_settings/tsconfig.json" }, { "path": "../src/plugins/management/tsconfig.json" }, { "path": "../src/plugins/bfetch/tsconfig.json" }, + { "path": "../src/plugins/charts/tsconfig.json" }, + { "path": "../src/plugins/console/tsconfig.json" }, + { "path": "../src/plugins/dashboard/tsconfig.json" }, + { "path": "../src/plugins/discover/tsconfig.json" }, { "path": "../src/plugins/embeddable/tsconfig.json" }, + { "path": "../src/plugins/es_ui_shared/tsconfig.json" }, { "path": "../src/plugins/expressions/tsconfig.json" }, { "path": "../src/plugins/home/tsconfig.json" }, { "path": "../src/plugins/inspector/tsconfig.json" }, @@ -20,10 +27,12 @@ { "path": "../src/plugins/navigation/tsconfig.json" }, { "path": "../src/plugins/newsfeed/tsconfig.json" }, { "path": "../src/plugins/saved_objects/tsconfig.json" }, + { "path": "../src/plugins/saved_objects_management/tsconfig.json" }, { "path": "../src/plugins/saved_objects_tagging_oss/tsconfig.json" }, { "path": "../src/plugins/telemetry_collection_manager/tsconfig.json" }, { "path": "../src/plugins/telemetry/tsconfig.json" }, { "path": "../src/plugins/ui_actions/tsconfig.json" }, + { "path": "../src/plugins/url_forwarding/tsconfig.json" }, { "path": "../src/plugins/usage_collection/tsconfig.json" }, ] } diff --git a/tsconfig.json b/tsconfig.json index 20e2e57ce654e..b6742bffeab55 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,12 +7,18 @@ "exclude": [ "src/**/__fixtures__/**/*", "src/core/**/*", - "src/plugins/management/**/*", + "src/plugins/telemetry_management_section/**/*", + "src/plugins/advanced_settings/**/*", "src/plugins/apm_oss/**/*", "src/plugins/bfetch/**/*", + "src/plugins/charts/**/*", + "src/plugins/console/**/*", + "src/plugins/dashboard/**/*", + "src/plugins/discover/**/*", "src/plugins/data/**/*", "src/plugins/dev_tools/**/*", "src/plugins/embeddable/**/*", + "src/plugins/es_ui_shared/**/*", "src/plugins/expressions/**/*", "src/plugins/home/**/*", "src/plugins/inspector/**/*", @@ -20,17 +26,34 @@ "src/plugins/kibana_react/**/*", "src/plugins/kibana_usage_collection/**/*", "src/plugins/kibana_utils/**/*", + "src/plugins/lens_oss/**/*", + "src/plugins/management/**/*", "src/plugins/navigation/**/*", "src/plugins/newsfeed/**/*", "src/plugins/saved_objects/**/*", - "src/plugins/security_oss/**/*", + "src/plugins/saved_objects_management/**/*", "src/plugins/saved_objects_tagging_oss/**/*", + "src/plugins/security_oss/**/*", "src/plugins/share/**/*", + "src/plugins/spaces_oss/**/*", "src/plugins/telemetry/**/*", "src/plugins/telemetry_collection_manager/**/*", + "src/plugins/timelion/**/*", "src/plugins/ui_actions/**/*", "src/plugins/url_forwarding/**/*", - "src/plugins/usage_collection/**/*" + "src/plugins/usage_collection/**/*", + "src/plugins/presentation_util/**/*", + "src/plugins/vis_default_editor/**/*", + "src/plugins/vis_type_markdown/**/*", + "src/plugins/vis_type_metric/**/*", + "src/plugins/vis_type_table/**/*", + "src/plugins/vis_type_tagcloud/**/*", + "src/plugins/vis_type_timelion/**/*", + "src/plugins/vis_type_timeseries/**/*", + "src/plugins/vis_type_vislib/**/*", + "src/plugins/vis_type_xy/**/*", + "src/plugins/visualizations/**/*", + "src/plugins/visualize/**/*", // In the build we actually exclude **/public/**/* from this config so that // we can run the TSC on both this and the .browser version of this config // file, but if we did it during development IDEs would not be able to find @@ -39,12 +62,18 @@ ], "references": [ { "path": "./src/core/tsconfig.json" }, - { "path": "./src/plugins/management/tsconfig.json"}, + { "path": "./src/plugins/telemetry_management_section/tsconfig.json" }, + { "path": "./src/plugins/advanced_settings/tsconfig.json" }, { "path": "./src/plugins/apm_oss/tsconfig.json" }, { "path": "./src/plugins/bfetch/tsconfig.json" }, + { "path": "./src/plugins/charts/tsconfig.json" }, + { "path": "./src/plugins/console/tsconfig.json" }, + { "path": "./src/plugins/dashboard/tsconfig.json" }, + { "path": "./src/plugins/discover/tsconfig.json" }, { "path": "./src/plugins/data/tsconfig.json" }, { "path": "./src/plugins/dev_tools/tsconfig.json" }, { "path": "./src/plugins/embeddable/tsconfig.json" }, + { "path": "./src/plugins/es_ui_shared/tsconfig.json" }, { "path": "./src/plugins/expressions/tsconfig.json" }, { "path": "./src/plugins/home/tsconfig.json" }, { "path": "./src/plugins/inspector/tsconfig.json" }, @@ -52,16 +81,32 @@ { "path": "./src/plugins/kibana_react/tsconfig.json" }, { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/lens_oss/tsconfig.json" }, + { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, { "path": "./src/plugins/saved_objects/tsconfig.json" }, + { "path": "./src/plugins/saved_objects_management/tsconfig.json" }, { "path": "./src/plugins/saved_objects_tagging_oss/tsconfig.json" }, { "path": "./src/plugins/security_oss/tsconfig.json" }, { "path": "./src/plugins/share/tsconfig.json" }, + { "path": "./src/plugins/spaces_oss/tsconfig.json" }, { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "./src/plugins/timelion/tsconfig.json" }, { "path": "./src/plugins/ui_actions/tsconfig.json" }, { "path": "./src/plugins/url_forwarding/tsconfig.json" }, - { "path": "./src/plugins/usage_collection/tsconfig.json" } + { "path": "./src/plugins/usage_collection/tsconfig.json" }, + { "path": "./src/plugins/vis_default_editor/tsconfig.json" }, + { "path": "./src/plugins/vis_type_markdown/tsconfig.json" }, + { "path": "./src/plugins/vis_type_metric/tsconfig.json" }, + { "path": "./src/plugins/vis_type_table/tsconfig.json" }, + { "path": "./src/plugins/vis_type_tagcloud/tsconfig.json" }, + { "path": "./src/plugins/vis_type_timelion/tsconfig.json" }, + { "path": "./src/plugins/vis_type_timeseries/tsconfig.json" }, + { "path": "./src/plugins/vis_type_vislib/tsconfig.json" }, + { "path": "./src/plugins/vis_type_xy/tsconfig.json" }, + { "path": "./src/plugins/visualizations/tsconfig.json" }, + { "path": "./src/plugins/visualize/tsconfig.json" }, ] } diff --git a/tsconfig.refs.json b/tsconfig.refs.json index c27d2ff2ec6f0..1bce19e2ee44a 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -2,29 +2,53 @@ "include": [], "references": [ { "path": "./src/core/tsconfig.json" }, + { "path": "./src/plugins/telemetry_management_section/tsconfig.json" }, + { "path": "./src/plugins/advanced_settings/tsconfig.json" }, { "path": "./src/plugins/apm_oss/tsconfig.json" }, { "path": "./src/plugins/bfetch/tsconfig.json" }, + { "path": "./src/plugins/charts/tsconfig.json" }, + { "path": "./src/plugins/console/tsconfig.json" }, { "path": "./src/plugins/data/tsconfig.json" }, { "path": "./src/plugins/dev_tools/tsconfig.json" }, + { "path": "./src/plugins/discover/tsconfig.json" }, { "path": "./src/plugins/embeddable/tsconfig.json" }, + { "path": "./src/plugins/es_ui_shared/tsconfig.json" }, { "path": "./src/plugins/expressions/tsconfig.json" }, { "path": "./src/plugins/home/tsconfig.json" }, + { "path": "./src/plugins/dashboard/tsconfig.json" }, + { "path": "./src/plugins/dev_tools/tsconfig.json" }, { "path": "./src/plugins/inspector/tsconfig.json" }, { "path": "./src/plugins/kibana_legacy/tsconfig.json" }, { "path": "./src/plugins/kibana_react/tsconfig.json" }, { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/lens_oss/tsconfig.json" }, + { "path": "./src/plugins/management/tsconfig.json" }, { "path": "./src/plugins/navigation/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, { "path": "./src/plugins/saved_objects/tsconfig.json" }, + { "path": "./src/plugins/saved_objects_management/tsconfig.json" }, { "path": "./src/plugins/saved_objects_tagging_oss/tsconfig.json" }, + { "path": "./src/plugins/presentation_util/tsconfig.json" }, { "path": "./src/plugins/security_oss/tsconfig.json" }, { "path": "./src/plugins/share/tsconfig.json" }, + { "path": "./src/plugins/spaces_oss/tsconfig.json" }, { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "./src/plugins/timelion/tsconfig.json" }, { "path": "./src/plugins/ui_actions/tsconfig.json" }, { "path": "./src/plugins/url_forwarding/tsconfig.json" }, { "path": "./src/plugins/usage_collection/tsconfig.json" }, - { "path": "./src/plugins/management/tsconfig.json" }, + { "path": "./src/plugins/vis_default_editor/tsconfig.json" }, + { "path": "./src/plugins/vis_type_markdown/tsconfig.json" }, + { "path": "./src/plugins/vis_type_metric/tsconfig.json" }, + { "path": "./src/plugins/vis_type_table/tsconfig.json" }, + { "path": "./src/plugins/vis_type_tagcloud/tsconfig.json" }, + { "path": "./src/plugins/vis_type_timelion/tsconfig.json" }, + { "path": "./src/plugins/vis_type_timeseries/tsconfig.json" }, + { "path": "./src/plugins/vis_type_vislib/tsconfig.json" }, + { "path": "./src/plugins/vis_type_xy/tsconfig.json" }, + { "path": "./src/plugins/visualizations/tsconfig.json" }, + { "path": "./src/plugins/visualize/tsconfig.json" }, ] } diff --git a/vars/kibanaCoverage.groovy b/vars/kibanaCoverage.groovy index 521672e4bf48c..019eb8088dbfc 100644 --- a/vars/kibanaCoverage.groovy +++ b/vars/kibanaCoverage.groovy @@ -60,7 +60,6 @@ def uploadCoverageHtmls(prefix) { [ 'target/kibana-coverage/functional-combined', 'target/kibana-coverage/jest-combined', - 'target/kibana-coverage/mocha-combined', ].each { uploadWithVault(prefix, it) } } @@ -78,7 +77,6 @@ def prokLinks(title) { kibanaPipeline.bash(''' cat << EOF > src/dev/code_coverage/www/index_partial_2.html Latest Jest - Latest Mocha Latest FTR
    @@ -151,7 +149,6 @@ def generateReports(title) { . src/dev/code_coverage/shell_scripts/extract_archives.sh . src/dev/code_coverage/shell_scripts/fix_html_reports_parallel.sh . src/dev/code_coverage/shell_scripts/merge_jest_and_functional.sh - . src/dev/code_coverage/shell_scripts/copy_mocha_reports.sh # zip combined reports tar -czf kibana-coverage.tar.gz target/kibana-coverage/**/* """, title) diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 7380d25930bc0..6937862d20536 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -42,7 +42,7 @@ "xpack.remoteClusters": "plugins/remote_clusters", "xpack.reporting": ["plugins/reporting"], "xpack.rollupJobs": ["plugins/rollup"], - "xpack.runtimeFields": "plugins/runtime_field_editor", + "xpack.runtimeFields": "plugins/runtime_fields", "xpack.searchProfiler": "plugins/searchprofiler", "xpack.security": "plugins/security", "xpack.server": "legacy/server", diff --git a/x-pack/examples/embedded_lens_example/.eslintrc.json b/x-pack/examples/embedded_lens_example/.eslintrc.json new file mode 100644 index 0000000000000..2aab6c2d9093b --- /dev/null +++ b/x-pack/examples/embedded_lens_example/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "@typescript-eslint/consistent-type-definitions": 0 + } +} diff --git a/x-pack/examples/embedded_lens_example/README.md b/x-pack/examples/embedded_lens_example/README.md new file mode 100644 index 0000000000000..ac9ba99569c6d --- /dev/null +++ b/x-pack/examples/embedded_lens_example/README.md @@ -0,0 +1,13 @@ +# Embedded Lens examples + +To run this example plugin, use the command `yarn start --run-examples`. + +This example shows how to embed Lens into other applications. Using the `EmbeddableComponent` of the `lens` start plugin, +you can pass in a valid Lens configuration which will get rendered the same way Lens dashboard panels work. Updating the +configuration will reload the embedded visualization. + +## Link to editor + +It is possible to use the same configuration and the `navigateToPrefilledEditor` method to navigate the current user to a +prefilled Lens editor so they can manipulate the configuration on their own and even save the results to a dashboard. +Make sure to always check permissions using `canUseEditor` whether the current user has permissions to access Lens. \ No newline at end of file diff --git a/x-pack/examples/embedded_lens_example/kibana.json b/x-pack/examples/embedded_lens_example/kibana.json new file mode 100644 index 0000000000000..5e4caead90bc3 --- /dev/null +++ b/x-pack/examples/embedded_lens_example/kibana.json @@ -0,0 +1,15 @@ +{ + "id": "embeddedLensExample", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["embedded_lens_example"], + "server": false, + "ui": true, + "requiredPlugins": [ + "lens", + "data", + "developerExamples" + ], + "optionalPlugins": [], + "requiredBundles": [] +} diff --git a/x-pack/examples/embedded_lens_example/package.json b/x-pack/examples/embedded_lens_example/package.json new file mode 100644 index 0000000000000..f66a0d5adba4e --- /dev/null +++ b/x-pack/examples/embedded_lens_example/package.json @@ -0,0 +1,14 @@ +{ + "name": "embedded_lens_example", + "version": "1.0.0", + "main": "target/examples/embedded_lens_example", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../../scripts/kbn.js", + "build": "rm -rf './target' && ../../../node_modules/.bin/tsc" + } +} \ No newline at end of file diff --git a/x-pack/examples/embedded_lens_example/public/app.tsx b/x-pack/examples/embedded_lens_example/public/app.tsx new file mode 100644 index 0000000000000..9f35907ca335d --- /dev/null +++ b/x-pack/examples/embedded_lens_example/public/app.tsx @@ -0,0 +1,180 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageHeader, + EuiPageHeaderSection, + EuiTitle, +} from '@elastic/eui'; +import { IndexPattern } from 'src/plugins/data/public'; +import { CoreStart } from 'kibana/public'; +import { TypedLensByValueInput } from '../../../plugins/lens/public'; +import { StartDependencies } from './plugin'; + +// Generate a Lens state based on some app-specific input parameters. +// `TypedLensByValueInput` can be used for type-safety - it uses the same interfaces as Lens-internal code. +function getLensAttributes( + defaultIndexPattern: IndexPattern, + color: string +): TypedLensByValueInput['attributes'] { + return { + visualizationType: 'lnsXY', + title: 'Prefilled from example app', + references: [ + { + id: defaultIndexPattern.id!, + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: defaultIndexPattern.id!, + name: 'indexpattern-datasource-layer-layer1', + type: 'index-pattern', + }, + ], + state: { + datasourceStates: { + indexpattern: { + layers: { + layer1: { + columnOrder: ['col1', 'col2'], + columns: { + col2: { + dataType: 'number', + isBucketed: false, + label: 'Count of records', + operationType: 'count', + scale: 'ratio', + sourceField: 'Records', + }, + col1: { + dataType: 'date', + isBucketed: true, + label: '@timestamp', + operationType: 'date_histogram', + params: { interval: 'auto' }, + scale: 'interval', + sourceField: defaultIndexPattern.timeFieldName!, + }, + }, + }, + }, + }, + }, + filters: [], + query: { language: 'kuery', query: '' }, + visualization: { + axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true }, + fittingFunction: 'None', + gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true }, + layers: [ + { + accessors: ['col2'], + layerId: 'layer1', + seriesType: 'bar_stacked', + xAccessor: 'col1', + yConfig: [{ forAccessor: 'col2', color }], + }, + ], + legend: { isVisible: true, position: 'right' }, + preferredSeriesType: 'bar_stacked', + tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, + valueLabels: 'hide', + }, + }, + }; +} + +export const App = (props: { + core: CoreStart; + plugins: StartDependencies; + defaultIndexPattern: IndexPattern | null; +}) => { + const [color, setColor] = useState('green'); + const LensComponent = props.plugins.lens.EmbeddableComponent; + return ( + + + + + +

    Embedded Lens vis

    +
    +
    +
    + + +

    + This app embeds a Lens visualization by specifying the configuration. Data fetching + and rendering is completely managed by Lens itself. +

    +

    + The Change color button will update the configuration by picking a new random color of + the series which causes Lens to re-render. The Edit button will take the current + configuration and navigate to a prefilled editor. +

    + {props.defaultIndexPattern && props.defaultIndexPattern.isTimeBased() ? ( + <> + + + { + // eslint-disable-next-line no-bitwise + const newColor = '#' + ((Math.random() * 0xffffff) << 0).toString(16); + setColor(newColor); + }} + > + Change color + + + + { + props.plugins.lens.navigateToPrefilledEditor({ + id: '', + timeRange: { + from: 'now-5d', + to: 'now', + }, + attributes: getLensAttributes(props.defaultIndexPattern!, color), + }); + // eslint-disable-next-line no-bitwise + const newColor = '#' + ((Math.random() * 0xffffff) << 0).toString(16); + setColor(newColor); + }} + > + Edit + + + + + + ) : ( +

    This demo only works if your default index pattern is set and time based

    + )} +
    +
    +
    +
    + ); +}; diff --git a/x-pack/plugins/apm/public/utils/isValidCoordinateValue.ts b/x-pack/examples/embedded_lens_example/public/index.ts similarity index 59% rename from x-pack/plugins/apm/public/utils/isValidCoordinateValue.ts rename to x-pack/examples/embedded_lens_example/public/index.ts index c36efc232b782..b9a263d5e6e88 100644 --- a/x-pack/plugins/apm/public/utils/isValidCoordinateValue.ts +++ b/x-pack/examples/embedded_lens_example/public/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { Maybe } from '../../typings/common'; -export const isValidCoordinateValue = (value: Maybe): value is number => - value !== null && value !== undefined; +import { EmbeddedLensExamplePlugin } from './plugin'; + +export const plugin = () => new EmbeddedLensExamplePlugin(); diff --git a/x-pack/examples/embedded_lens_example/public/mount.tsx b/x-pack/examples/embedded_lens_example/public/mount.tsx new file mode 100644 index 0000000000000..21d0a01df1636 --- /dev/null +++ b/x-pack/examples/embedded_lens_example/public/mount.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { CoreSetup, AppMountParameters } from 'kibana/public'; +import { StartDependencies } from './plugin'; + +export const mount = (coreSetup: CoreSetup) => async ({ + element, +}: AppMountParameters) => { + const [core, plugins] = await coreSetup.getStartServices(); + const { App } = await import('./app'); + + const deps = { + core, + plugins, + }; + + const defaultIndexPattern = await plugins.data.indexPatterns.getDefault(); + + const reactElement = ; + render(reactElement, element); + return () => unmountComponentAtNode(element); +}; diff --git a/x-pack/examples/embedded_lens_example/public/plugin.ts b/x-pack/examples/embedded_lens_example/public/plugin.ts new file mode 100644 index 0000000000000..2f2e988d42025 --- /dev/null +++ b/x-pack/examples/embedded_lens_example/public/plugin.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin, CoreSetup, AppNavLinkStatus } from '../../../../src/core/public'; +import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import { LensPublicStart } from '../../../plugins/lens/public'; +import { DeveloperExamplesSetup } from '../../../../examples/developer_examples/public'; +import { mount } from './mount'; + +export interface SetupDependencies { + developerExamples: DeveloperExamplesSetup; +} + +export interface StartDependencies { + data: DataPublicPluginStart; + lens: LensPublicStart; +} + +export class EmbeddedLensExamplePlugin + implements Plugin { + public setup(core: CoreSetup, { developerExamples }: SetupDependencies) { + core.application.register({ + id: 'embedded_lens_example', + title: 'Embedded Lens example', + navLinkStatus: AppNavLinkStatus.hidden, + mount: mount(core), + }); + + developerExamples.register({ + appId: 'embedded_lens_example', + title: 'Embedded Lens', + description: + 'Embed Lens visualizations into other applications and link to a pre-configured Lens editor to allow users to use visualizations in your app as starting points for further explorations.', + links: [ + { + label: 'README', + href: + 'https://github.com/elastic/kibana/tree/master/x-pack/examples/embedded_lens_example', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); + } + + public start() {} + + public stop() {} +} diff --git a/x-pack/examples/embedded_lens_example/tsconfig.json b/x-pack/examples/embedded_lens_example/tsconfig.json new file mode 100644 index 0000000000000..2bf577e87041c --- /dev/null +++ b/x-pack/examples/embedded_lens_example/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../typings/**/*" + ], + "exclude": [], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/share/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" } + ] +} diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts index 7e938e766657c..e106b17ad223f 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts @@ -5,10 +5,11 @@ */ import axios from 'axios'; -import HttpProxyAgent from 'http-proxy-agent'; import { Logger } from '../../../../../../src/core/server'; import { addTimeZoneToDate, request, patch, getErrorMessage } from './axios_utils'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; +import { getProxyAgents } from './get_proxy_agents'; + const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios'); const axiosMock = (axios as unknown) as jest.Mock; @@ -27,6 +28,7 @@ describe('addTimeZoneToDate', () => { describe('request', () => { beforeEach(() => { + jest.resetAllMocks(); axiosMock.mockImplementation(() => ({ status: 200, headers: { 'content-type': 'application/json' }, @@ -44,12 +46,9 @@ describe('request', () => { expect(axiosMock).toHaveBeenCalledWith('/test', { method: 'get', data: {}, - headers: undefined, httpAgent: undefined, httpsAgent: undefined, - params: undefined, proxy: false, - validateStatus: undefined, }); expect(res).toEqual({ status: 200, @@ -58,26 +57,54 @@ describe('request', () => { }); }); - test('it have been called with proper proxy agent', async () => { + test('it have been called with proper proxy agent for a valid url', async () => { + const proxySettings = { + proxyRejectUnauthorizedCertificates: true, + proxyUrl: 'https://localhost:1212', + }; + const { httpAgent, httpsAgent } = getProxyAgents(proxySettings, logger); + + const res = await request({ + axios, + url: 'http://testProxy', + logger, + proxySettings: { + proxyUrl: 'https://localhost:1212', + proxyRejectUnauthorizedCertificates: true, + }, + }); + + expect(axiosMock).toHaveBeenCalledWith('http://testProxy', { + method: 'get', + data: {}, + httpAgent, + httpsAgent, + proxy: false, + }); + expect(res).toEqual({ + status: 200, + headers: { 'content-type': 'application/json' }, + data: { incidentId: '123' }, + }); + }); + + test('it have been called with proper proxy agent for an invalid url', async () => { const res = await request({ axios, - url: '/testProxy', + url: 'https://testProxy', logger, proxySettings: { - proxyUrl: 'http://localhost:1212', + proxyUrl: ':nope:', proxyRejectUnauthorizedCertificates: false, }, }); - expect(axiosMock).toHaveBeenCalledWith('/testProxy', { + expect(axiosMock).toHaveBeenCalledWith('https://testProxy', { method: 'get', data: {}, - headers: undefined, - httpAgent: new HttpProxyAgent('http://localhost:1212'), - httpsAgent: new HttpProxyAgent('http://localhost:1212'), - params: undefined, + httpAgent: undefined, + httpsAgent: undefined, proxy: false, - validateStatus: undefined, }); expect(res).toEqual({ status: 200, @@ -92,12 +119,9 @@ describe('request', () => { expect(axiosMock).toHaveBeenCalledWith('/test', { method: 'post', data: { id: '123' }, - headers: undefined, httpAgent: undefined, httpsAgent: undefined, - params: undefined, proxy: false, - validateStatus: undefined, }); expect(res).toEqual({ status: 200, @@ -120,12 +144,9 @@ describe('patch', () => { expect(axiosMock).toHaveBeenCalledWith('/test', { method: 'patch', data: { id: '123' }, - headers: undefined, httpAgent: undefined, httpsAgent: undefined, - params: undefined, proxy: false, - validateStatus: undefined, }); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index e26a3b686179c..78c6b91b57dc0 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -7,7 +7,7 @@ import { AxiosInstance, Method, AxiosResponse, AxiosBasicCredentials } from 'axios'; import { Logger } from '../../../../../../src/core/server'; import { ProxySettings } from '../../types'; -import { getProxyAgent } from './get_proxy_agent'; +import { getProxyAgents } from './get_proxy_agents'; export const request = async ({ axios, @@ -15,11 +15,8 @@ export const request = async ({ logger, method = 'get', data, - params, proxySettings, - headers, - validateStatus, - auth, + ...rest }: { axios: AxiosInstance; url: string; @@ -32,17 +29,16 @@ export const request = async ({ validateStatus?: (status: number) => boolean; auth?: AxiosBasicCredentials; }): Promise => { + const { httpAgent, httpsAgent } = getProxyAgents(proxySettings, logger); + return await axios(url, { + ...rest, method, data: data ?? {}, - params, - auth, - // use httpsAgent and embedded proxy: false, to be able to handle fail on invalid certs - httpsAgent: proxySettings ? getProxyAgent(proxySettings, logger) : undefined, - httpAgent: proxySettings ? getProxyAgent(proxySettings, logger) : undefined, - proxy: false, // the same way as it done for IncomingWebhook in - headers, - validateStatus, + // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs + httpAgent, + httpsAgent, + proxy: false, }); }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.test.ts deleted file mode 100644 index 8623a67e8a68e..0000000000000 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import HttpProxyAgent from 'http-proxy-agent'; -import { HttpsProxyAgent } from 'https-proxy-agent'; -import { Logger } from '../../../../../../src/core/server'; -import { getProxyAgent } from './get_proxy_agent'; -import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; -const logger = loggingSystemMock.create().get() as jest.Mocked; - -describe('getProxyAgent', () => { - test('return HttpsProxyAgent for https proxy url', () => { - const agent = getProxyAgent( - { proxyUrl: 'https://someproxyhost', proxyRejectUnauthorizedCertificates: false }, - logger - ); - expect(agent instanceof HttpsProxyAgent).toBeTruthy(); - }); - - test('return HttpProxyAgent for http proxy url', () => { - const agent = getProxyAgent( - { proxyUrl: 'http://someproxyhost', proxyRejectUnauthorizedCertificates: false }, - logger - ); - expect(agent instanceof HttpProxyAgent).toBeTruthy(); - }); -}); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.ts deleted file mode 100644 index 957d31546b019..0000000000000 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agent.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import HttpProxyAgent from 'http-proxy-agent'; -import { HttpsProxyAgent } from 'https-proxy-agent'; -import { Logger } from '../../../../../../src/core/server'; -import { ProxySettings } from '../../types'; - -export function getProxyAgent( - proxySettings: ProxySettings, - logger: Logger -): HttpsProxyAgent | HttpProxyAgent { - logger.debug(`Create proxy agent for ${proxySettings.proxyUrl}.`); - - if (/^https/i.test(proxySettings.proxyUrl)) { - const proxyUrl = new URL(proxySettings.proxyUrl); - return new HttpsProxyAgent({ - host: proxyUrl.hostname, - port: Number(proxyUrl.port), - protocol: proxyUrl.protocol, - headers: proxySettings.proxyHeaders, - // do not fail on invalid certs if value is false - rejectUnauthorized: proxySettings.proxyRejectUnauthorizedCertificates, - }); - } else { - return new HttpProxyAgent(proxySettings.proxyUrl); - } -} diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.test.ts new file mode 100644 index 0000000000000..759ca92968263 --- /dev/null +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import HttpProxyAgent from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import { Logger } from '../../../../../../src/core/server'; +import { getProxyAgents } from './get_proxy_agents'; +import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; +const logger = loggingSystemMock.create().get() as jest.Mocked; + +describe('getProxyAgents', () => { + test('get agents for valid proxy URL', () => { + const { httpAgent, httpsAgent } = getProxyAgents( + { proxyUrl: 'https://someproxyhost', proxyRejectUnauthorizedCertificates: false }, + logger + ); + expect(httpAgent instanceof HttpProxyAgent).toBeTruthy(); + expect(httpsAgent instanceof HttpsProxyAgent).toBeTruthy(); + }); + + test('return undefined agents for invalid proxy URL', () => { + const { httpAgent, httpsAgent } = getProxyAgents( + { proxyUrl: ':nope: not a valid URL', proxyRejectUnauthorizedCertificates: false }, + logger + ); + expect(httpAgent).toBe(undefined); + expect(httpsAgent).toBe(undefined); + }); + + test('return undefined agents for null proxy options', () => { + const { httpAgent, httpsAgent } = getProxyAgents(null, logger); + expect(httpAgent).toBe(undefined); + expect(httpsAgent).toBe(undefined); + }); + + test('return undefined agents for undefined proxy options', () => { + const { httpAgent, httpsAgent } = getProxyAgents(undefined, logger); + expect(httpAgent).toBe(undefined); + expect(httpsAgent).toBe(undefined); + }); +}); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.ts new file mode 100644 index 0000000000000..45f962429ad2b --- /dev/null +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/get_proxy_agents.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Agent } from 'http'; +import HttpProxyAgent from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import { Logger } from '../../../../../../src/core/server'; +import { ProxySettings } from '../../types'; + +interface GetProxyAgentsResponse { + httpAgent: Agent | undefined; + httpsAgent: Agent | undefined; +} + +export function getProxyAgents( + proxySettings: ProxySettings | undefined | null, + logger: Logger +): GetProxyAgentsResponse { + const undefinedResponse = { + httpAgent: undefined, + httpsAgent: undefined, + }; + + if (!proxySettings) { + return undefinedResponse; + } + + logger.debug(`Creating proxy agents for proxy: ${proxySettings.proxyUrl}`); + let proxyUrl: URL; + try { + proxyUrl = new URL(proxySettings.proxyUrl); + } catch (err) { + logger.warn(`invalid proxy URL "${proxySettings.proxyUrl}" ignored`); + return undefinedResponse; + } + + const httpAgent = new HttpProxyAgent(proxySettings.proxyUrl); + const httpsAgent = (new HttpsProxyAgent({ + host: proxyUrl.hostname, + port: Number(proxyUrl.port), + protocol: proxyUrl.protocol, + headers: proxySettings.proxyHeaders, + // do not fail on invalid certs if value is false + rejectUnauthorized: proxySettings.proxyRejectUnauthorizedCertificates, + }) as unknown) as Agent; + // vsCode wasn't convinced HttpsProxyAgent is an http.Agent, so we convinced it + + return { httpAgent, httpsAgent }; +} diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.ts index 2105b267bc298..02026eb729727 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.ts @@ -6,8 +6,7 @@ import { URL } from 'url'; import { curry } from 'lodash'; -import { HttpsProxyAgent } from 'https-proxy-agent'; -import HttpProxyAgent from 'http-proxy-agent'; +import { Agent } from 'http'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { IncomingWebhook, IncomingWebhookResult } from '@slack/webhook'; @@ -24,7 +23,7 @@ import { ExecutorType, } from '../types'; import { ActionsConfigurationUtilities } from '../actions_config'; -import { getProxyAgent } from './lib/get_proxy_agent'; +import { getProxyAgents } from './lib/get_proxy_agents'; export type SlackActionType = ActionType<{}, ActionTypeSecretsType, ActionParamsType, unknown>; export type SlackActionTypeExecutorOptions = ActionTypeExecutorOptions< @@ -128,9 +127,13 @@ async function slackExecutor( const { webhookUrl } = secrets; const { message } = params; - let proxyAgent: HttpsProxyAgent | HttpProxyAgent | undefined; + let httpProxyAgent: Agent | undefined; if (execOptions.proxySettings) { - proxyAgent = getProxyAgent(execOptions.proxySettings, logger); + const httpProxyAgents = getProxyAgents(execOptions.proxySettings, logger); + httpProxyAgent = webhookUrl.toLowerCase().startsWith('https') + ? httpProxyAgents.httpsAgent + : httpProxyAgents.httpAgent; + logger.debug(`IncomingWebhook was called with proxyUrl ${execOptions.proxySettings.proxyUrl}`); } @@ -138,8 +141,7 @@ async function slackExecutor( // https://slack.dev/node-slack-sdk/webhook // node-slack-sdk use Axios inside :) const webhook = new IncomingWebhook(webhookUrl, { - // @ts-expect-error The types exposed by 'HttpsProxyAgent' isn't up to date with 'Agent' - agent: proxyAgent, + agent: httpProxyAgent, }); result = await webhook.send(message); } catch (err) { diff --git a/x-pack/plugins/actions/server/manual_tests/forward_proxy.js b/x-pack/plugins/actions/server/manual_tests/forward_proxy.js new file mode 100644 index 0000000000000..5c48b9d2393ab --- /dev/null +++ b/x-pack/plugins/actions/server/manual_tests/forward_proxy.js @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* +This module implements two forward http proxies, http on 8080 and https on 8443, +which can be used with the config xpack.actions.proxyUrl to emulate customers +using forward proxies with Kibana actions. You can use either the http or https +versions, both can forward proxy http and https traffic: + + xpack.actions.proxyUrl: http://localhost:8080 + OR + xpack.actions.proxyUrl: https://localhost:8443 + +When using the https-based version, you may need to set the following option +as well: + + xpack.actions.rejectUnauthorized: false + +If the server you are connecting to via the proxy is https and has self-signed +certificates, you'll also need to set + + xpack.actions.proxyRejectUnauthorizedCertificates: false +*/ + +const HTTP_PORT = 8080; +const HTTPS_PORT = 8443; + +// starts http and https proxies to use to test actions within Kibana + +const fs = require('fs'); +const net = require('net'); +const url = require('url'); +const http = require('http'); +const https = require('https'); +const httpProxy = require('http-proxy'); + +const httpsOptions = { + key: fs.readFileSync('packages/kbn-dev-utils/certs/kibana.key', 'utf8'), + cert: fs.readFileSync('packages/kbn-dev-utils/certs/kibana.crt', 'utf8'), +}; + +const proxy = httpProxy.createServer(); + +createServer('http', HTTP_PORT); +createServer('https', HTTPS_PORT); + +function createServer(protocol, port) { + let httpServer; + + if (protocol === 'http') { + httpServer = http.createServer(); + } else { + httpServer = https.createServer(httpsOptions); + } + + httpServer.on('request', httpRequest); + httpServer.on('connect', httpsRequest); + httpServer.listen(port); + log(`proxy server started: ${protocol}:/localhost:${port}`); + + // handle http requests + function httpRequest(req, res) { + log(`${protocol} server: request for: ${req.url}`); + const parsedUrl = url.parse(req.url); + if (parsedUrl.hostname == null) { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end('this is a proxy server'); + return; + } + const target = parsedUrl.protocol + '//' + parsedUrl.hostname; + proxy.web(req, res, { target: target, secure: false }); + } + + // handle https requests + // see: https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_event_connect + function httpsRequest(req, socket, head) { + log(`${protocol} proxy server: request for target: https://${req.url}`); + const serverUrl = url.parse('https://' + req.url); + const serverSocket = net.connect(serverUrl.port, serverUrl.hostname, () => { + socket.write('HTTP/1.1 200 Connection Established\r\nProxy-agent: Node-Proxy\r\n\r\n'); + serverSocket.write(head); + serverSocket.pipe(socket); + socket.pipe(serverSocket); + }); + socket.on('error', (err) => { + log(`error on socket to proxy: ${err}`); + socket.destroy(); + serverSocket.destroy(); + }); + serverSocket.on('error', (err) => { + log(`error on socket to target: ${err}`); + socket.destroy(); + serverSocket.destroy(); + }); + } +} + +function log(message) { + console.log(`${new Date().toISOString()} - ${message}`); +} + +/* +Test with: + +curl -v -k --proxy-insecure -x http://127.0.0.1:8080 http://www.google.com +curl -v -k --proxy-insecure -x http://127.0.0.1:8080 https://www.google.com +curl -v -k --proxy-insecure -x https://127.0.0.1:8443 http://www.google.com +curl -v -k --proxy-insecure -x https://127.0.0.1:8443 https://www.google.com +*/ diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 7c41bf99af472..133e5f9c6aa2c 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -19,6 +19,7 @@ import { ElasticsearchServiceStart, ILegacyClusterClient, SavedObjectsClientContract, + SavedObjectsBulkGetObject, } from '../../../../src/core/server'; import { @@ -333,7 +334,12 @@ export class ActionsPlugin implements Plugin, Plugi this.eventLogService!.registerSavedObjectProvider('action', (request) => { const client = secureGetActionsClientWithRequest(request); - return async (type: string, id: string) => (await client).get({ id }); + return (objects?: SavedObjectsBulkGetObject[]) => + objects + ? Promise.all( + objects.map(async (objectItem) => await (await client).get({ id: objectItem.id })) + ) + : Promise.resolve([]); }); const getScopedSavedObjectsClientWithoutAccessToActions = (request: KibanaRequest) => diff --git a/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts b/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts index a47af44d330c3..b6606d9d7fe57 100644 --- a/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts +++ b/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts @@ -412,7 +412,7 @@ export class AlertsClient { this.logger.debug(`getAlertInstanceSummary(): search the event log for alert ${id}`); let events: IEvent[]; try { - const queryResults = await eventLogClient.findEventsBySavedObject('alert', id, { + const queryResults = await eventLogClient.findEventsBySavedObjectIds('alert', [id], { page: 1, per_page: 10000, start: parsedDateStart.toISOString(), diff --git a/x-pack/plugins/alerts/server/alerts_client/tests/get_alert_instance_summary.test.ts b/x-pack/plugins/alerts/server/alerts_client/tests/get_alert_instance_summary.test.ts index 555c316038daa..6c0612df030dd 100644 --- a/x-pack/plugins/alerts/server/alerts_client/tests/get_alert_instance_summary.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client/tests/get_alert_instance_summary.test.ts @@ -131,7 +131,7 @@ describe('getAlertInstanceSummary()', () => { total: events.length, data: events, }; - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce(eventsResult); + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce(eventsResult); const dateStart = new Date(Date.now() - 60 * 1000).toISOString(); @@ -188,18 +188,20 @@ describe('getAlertInstanceSummary()', () => { test('calls saved objects and event log client with default params', async () => { unsecuredSavedObjectsClient.get.mockResolvedValueOnce(getAlertInstanceSummarySavedObject()); - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce( + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce( AlertInstanceSummaryFindEventsResult ); await alertsClient.getAlertInstanceSummary({ id: '1' }); expect(unsecuredSavedObjectsClient.get).toHaveBeenCalledTimes(1); - expect(eventLogClient.findEventsBySavedObject).toHaveBeenCalledTimes(1); - expect(eventLogClient.findEventsBySavedObject.mock.calls[0]).toMatchInlineSnapshot(` + expect(eventLogClient.findEventsBySavedObjectIds).toHaveBeenCalledTimes(1); + expect(eventLogClient.findEventsBySavedObjectIds.mock.calls[0]).toMatchInlineSnapshot(` Array [ "alert", - "1", + Array [ + "1", + ], Object { "end": "2019-02-12T21:01:22.479Z", "page": 1, @@ -210,7 +212,7 @@ describe('getAlertInstanceSummary()', () => { ] `); // calculate the expected start/end date for one test - const { start, end } = eventLogClient.findEventsBySavedObject.mock.calls[0][2]!; + const { start, end } = eventLogClient.findEventsBySavedObjectIds.mock.calls[0][2]!; expect(end).toBe(mockedDateString); const startMillis = Date.parse(start!); @@ -222,7 +224,7 @@ describe('getAlertInstanceSummary()', () => { test('calls event log client with start date', async () => { unsecuredSavedObjectsClient.get.mockResolvedValueOnce(getAlertInstanceSummarySavedObject()); - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce( + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce( AlertInstanceSummaryFindEventsResult ); @@ -232,8 +234,8 @@ describe('getAlertInstanceSummary()', () => { await alertsClient.getAlertInstanceSummary({ id: '1', dateStart }); expect(unsecuredSavedObjectsClient.get).toHaveBeenCalledTimes(1); - expect(eventLogClient.findEventsBySavedObject).toHaveBeenCalledTimes(1); - const { start, end } = eventLogClient.findEventsBySavedObject.mock.calls[0][2]!; + expect(eventLogClient.findEventsBySavedObjectIds).toHaveBeenCalledTimes(1); + const { start, end } = eventLogClient.findEventsBySavedObjectIds.mock.calls[0][2]!; expect({ start, end }).toMatchInlineSnapshot(` Object { @@ -245,7 +247,7 @@ describe('getAlertInstanceSummary()', () => { test('calls event log client with relative start date', async () => { unsecuredSavedObjectsClient.get.mockResolvedValueOnce(getAlertInstanceSummarySavedObject()); - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce( + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce( AlertInstanceSummaryFindEventsResult ); @@ -253,8 +255,8 @@ describe('getAlertInstanceSummary()', () => { await alertsClient.getAlertInstanceSummary({ id: '1', dateStart }); expect(unsecuredSavedObjectsClient.get).toHaveBeenCalledTimes(1); - expect(eventLogClient.findEventsBySavedObject).toHaveBeenCalledTimes(1); - const { start, end } = eventLogClient.findEventsBySavedObject.mock.calls[0][2]!; + expect(eventLogClient.findEventsBySavedObjectIds).toHaveBeenCalledTimes(1); + const { start, end } = eventLogClient.findEventsBySavedObjectIds.mock.calls[0][2]!; expect({ start, end }).toMatchInlineSnapshot(` Object { @@ -266,7 +268,7 @@ describe('getAlertInstanceSummary()', () => { test('invalid start date throws an error', async () => { unsecuredSavedObjectsClient.get.mockResolvedValueOnce(getAlertInstanceSummarySavedObject()); - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce( + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce( AlertInstanceSummaryFindEventsResult ); @@ -280,7 +282,7 @@ describe('getAlertInstanceSummary()', () => { test('saved object get throws an error', async () => { unsecuredSavedObjectsClient.get.mockRejectedValueOnce(new Error('OMG!')); - eventLogClient.findEventsBySavedObject.mockResolvedValueOnce( + eventLogClient.findEventsBySavedObjectIds.mockResolvedValueOnce( AlertInstanceSummaryFindEventsResult ); @@ -291,7 +293,7 @@ describe('getAlertInstanceSummary()', () => { test('findEvents throws an error', async () => { unsecuredSavedObjectsClient.get.mockResolvedValueOnce(getAlertInstanceSummarySavedObject()); - eventLogClient.findEventsBySavedObject.mockRejectedValueOnce(new Error('OMG 2!')); + eventLogClient.findEventsBySavedObjectIds.mockRejectedValueOnce(new Error('OMG 2!')); // error eaten but logged await alertsClient.getAlertInstanceSummary({ id: '1' }); diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index d15ae0ca55ef9..cb165fa56d046 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -33,6 +33,7 @@ import { ILegacyClusterClient, StatusServiceSetup, ServiceStatus, + SavedObjectsBulkGetObject, } from '../../../../src/core/server'; import { @@ -370,7 +371,10 @@ export class AlertingPlugin { this.eventLogService!.registerSavedObjectProvider('alert', (request) => { const client = getAlertsClientWithRequest(request); - return (type: string, id: string) => client.get({ id }); + return (objects?: SavedObjectsBulkGetObject[]) => + objects + ? Promise.all(objects.map(async (objectItem) => await client.get({ id: objectItem.id }))) + : Promise.resolve([]); }); scheduleAlertingTelemetry(this.telemetryLogger, plugins.taskManager); diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index bd2e18b66c8e3..a41faba2e9382 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -125,7 +125,7 @@ export const generalSettings: RawSettingDefinition[] = [ defaultMessage: 'When recording, the agent instruments incoming HTTP requests, tracks errors, and collects and sends metrics. When set to non-recording, the agent works as a noop, not collecting data and not communicating with the APM Server except for polling for updated configuration. As this is a reversible switch, agent threads are not being killed when set to non-recording, but they will be mostly idle in this state, so the overhead should be negligible. You can use this setting to dynamically control whether Elastic APM is enabled or disabled.', }), - excludeAgents: ['nodejs'], + excludeAgents: ['nodejs', 'rum-js', 'js-base'], }, // SERVER_TIMEOUT diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts index f7209d8b46edb..4f319e4dd7016 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts @@ -87,14 +87,12 @@ describe('filterByAgent', () => { it('js-base', () => { expect(getSettingKeysForAgent('js-base')).toEqual([ - 'recording', 'transaction_sample_rate', ]); }); it('rum-js', () => { expect(getSettingKeysForAgent('rum-js')).toEqual([ - 'recording', 'transaction_sample_rate', ]); }); diff --git a/x-pack/plugins/apm/common/utils/formatters/formatters.ts b/x-pack/plugins/apm/common/utils/formatters/formatters.ts index 50ce9db096610..7b21a686209ae 100644 --- a/x-pack/plugins/apm/common/utils/formatters/formatters.ts +++ b/x-pack/plugins/apm/common/utils/formatters/formatters.ts @@ -8,11 +8,19 @@ import { Maybe } from '../../../typings/common'; import { NOT_AVAILABLE_LABEL } from '../../i18n'; import { isFiniteNumber } from '../is_finite_number'; -export function asDecimal(value: number) { +export function asDecimal(value?: number | null) { + if (!isFiniteNumber(value)) { + return NOT_AVAILABLE_LABEL; + } + return numeral(value).format('0,0.0'); } -export function asInteger(value: number) { +export function asInteger(value?: number | null) { + if (!isFiniteNumber(value)) { + return NOT_AVAILABLE_LABEL; + } + return numeral(value).format('0,0'); } diff --git a/x-pack/plugins/apm/common/utils/join_by_key/index.ts b/x-pack/plugins/apm/common/utils/join_by_key/index.ts index 6678bf68afbae..d296fc44c1f24 100644 --- a/x-pack/plugins/apm/common/utils/join_by_key/index.ts +++ b/x-pack/plugins/apm/common/utils/join_by_key/index.ts @@ -9,11 +9,11 @@ import { isEqual, pull, merge, castArray } from 'lodash'; /** * Joins a list of records by a given key. Key can be any type of value, from * strings to plain objects, as long as it is present in all records. `isEqual` - * is used for comparing keys. - * + * is used for comparing keys. + * * UnionToIntersection is needed to get all keys of union types, see below for * example. - * + * const agentNames = [{ serviceName: '', agentName: '' }]; const transactionRates = [{ serviceName: '', transactionsPerMinute: 1 }]; const flattened = joinByKey( diff --git a/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx b/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx index 88a897d7baf50..83bbf49691be9 100644 --- a/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ import React, { useCallback, useMemo } from 'react'; +import { useParams } from 'react-router-dom'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { AlertType } from '../../../../common/alert_types'; +import { getInitialAlertValues } from '../get_initial_alert_values'; import { TriggersAndActionsUIPublicPluginStart } from '../../../../../triggers_actions_ui/public'; - interface Props { addFlyoutVisible: boolean; setAddFlyoutVisibility: React.Dispatch>; @@ -20,10 +21,13 @@ interface KibanaDeps { export function AlertingFlyout(props: Props) { const { addFlyoutVisible, setAddFlyoutVisibility, alertType } = props; + const { serviceName } = useParams<{ serviceName?: string }>(); const { services: { triggersActionsUi }, } = useKibana(); + const initialValues = getInitialAlertValues(alertType, serviceName); + const onCloseAddFlyout = useCallback(() => setAddFlyoutVisibility(false), [ setAddFlyoutVisibility, ]); @@ -36,7 +40,9 @@ export function AlertingFlyout(props: Props) { onClose: onCloseAddFlyout, alertTypeId: alertType, canChangeTrigger: false, + initialValues, }), + /* eslint-disable-next-line react-hooks/exhaustive-deps */ [alertType, onCloseAddFlyout, triggersActionsUi] ); return <>{addFlyoutVisible && addAlertFlyout}; diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx index cce973f8587da..d7375d14e17cf 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx @@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useParams } from 'react-router-dom'; import { ForLastExpression } from '../../../../../triggers_actions_ui/public'; -import { AlertType, ALERT_TYPES_CONFIG } from '../../../../common/alert_types'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; import { asInteger } from '../../../../common/utils/formatters'; import { useUrlParams } from '../../../context/url_params_context/use_url_params'; @@ -110,7 +109,6 @@ export function ErrorCountAlertTrigger(props: Props) { return ( { + expect(getInitialAlertValues(null, undefined)).toEqual({ tags: ['apm'] }); +}); + +test('handles valid alert type', () => { + const alertType = AlertType.ErrorCount; + expect(getInitialAlertValues(alertType, undefined)).toEqual({ + name: ALERT_TYPES_CONFIG[alertType].name, + tags: ['apm'], + }); + + expect(getInitialAlertValues(alertType, 'Service Name')).toEqual({ + name: `${ALERT_TYPES_CONFIG[alertType].name} | Service Name`, + tags: ['apm', `service.name:service name`], + }); +}); diff --git a/x-pack/plugins/apm/public/components/alerting/get_initial_alert_values.ts b/x-pack/plugins/apm/public/components/alerting/get_initial_alert_values.ts new file mode 100644 index 0000000000000..3655c9f90c4bf --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/get_initial_alert_values.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types'; + +export function getInitialAlertValues( + alertType: AlertType | null, + serviceName: string | undefined +) { + const alertTypeName = alertType + ? ALERT_TYPES_CONFIG[alertType].name + : undefined; + const alertName = alertTypeName + ? serviceName + ? `${alertTypeName} | ${serviceName}` + : alertTypeName + : undefined; + const tags = ['apm']; + if (serviceName) { + tags.push(`service.name:${serviceName}`.toLowerCase()); + } + + return { + tags, + ...(alertName ? { name: alertName } : {}), + }; +} diff --git a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/index.tsx index 0a12f79bf61a9..a04679bcb689d 100644 --- a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/index.tsx @@ -9,7 +9,6 @@ import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; interface Props { - alertTypeName: string; setAlertParams: (key: string, value: any) => void; setAlertProperty: (key: string, value: any) => void; defaults: Record; @@ -20,14 +19,7 @@ interface Props { export function ServiceAlertTrigger(props: Props) { const { serviceName } = useParams<{ serviceName?: string }>(); - const { - fields, - setAlertParams, - setAlertProperty, - alertTypeName, - defaults, - chartPreview, - } = props; + const { fields, setAlertParams, defaults, chartPreview } = props; const params: Record = { ...defaults, @@ -36,17 +28,6 @@ export function ServiceAlertTrigger(props: Props) { useEffect(() => { // we only want to run this on mount to set default values - - const alertName = params.serviceName - ? `${alertTypeName} | ${params.serviceName}` - : alertTypeName; - setAlertProperty('name', alertName); - - const tags = ['apm']; - if (params.serviceName) { - tags.push(`service.name:${params.serviceName}`.toLowerCase()); - } - setAlertProperty('tags', tags); Object.keys(params).forEach((key) => { setAlertParams(key, params[key]); }); diff --git a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/popover_expression/index.tsx b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/popover_expression/index.tsx index a95ea3cf11e7a..48e9b540a2d1d 100644 --- a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/popover_expression/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/popover_expression/index.tsx @@ -30,6 +30,7 @@ export function PopoverExpression(props: Props) { onClick={() => setPopoverOpen(true)} /> } + repositionOnScroll > {children} diff --git a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/service_alert_trigger.test.tsx b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/service_alert_trigger.test.tsx index 72611043bbed3..7f9a27e884e8e 100644 --- a/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/service_alert_trigger.test.tsx +++ b/x-pack/plugins/apm/public/components/alerting/service_alert_trigger/service_alert_trigger.test.tsx @@ -18,7 +18,6 @@ describe('ServiceAlertTrigger', () => { expect(() => render( {}} diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx index 22840bc2e6ed0..7c0a74f2e1b60 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { useParams } from 'react-router-dom'; import { useFetcher } from '../../../../../observability/public'; import { ForLastExpression } from '../../../../../triggers_actions_ui/public'; -import { ALERT_TYPES_CONFIG } from '../../../../common/alert_types'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; import { getDurationFormatter } from '../../../../common/utils/formatters'; import { TimeSeries } from '../../../../typings/timeseries'; @@ -203,7 +202,6 @@ export function TransactionDurationAlertTrigger(props: Props) { return ( } body={ - <> -

    - {i18n.translate( - 'xpack.apm.agentConfig.configTable.emptyPromptText', +

    + {i18n.translate('xpack.apm.agentConfig.configTable.emptyPromptText', { + defaultMessage: + "Let's change that! You can fine-tune agent configuration directly from Kibana without having to redeploy. Get started by creating your first configuration.", + })} +

    + } + actions={ + - - } - actions={ - - {i18n.translate( - 'xpack.apm.agentConfig.configTable.createConfigButtonLabel', - { defaultMessage: 'Create configuration' } - )} - + + {i18n.translate( + 'xpack.apm.agentConfig.configTable.createConfigButtonLabel', + { defaultMessage: 'Create configuration' } + )} + + } /> ); diff --git a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx index ba08af32d65b6..8c10b96c51ce2 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx @@ -248,7 +248,7 @@ export function ApmIndices() { fill onClick={handleApplyChangesEvent} isLoading={isSaving} - disabled={!canSave} + isDisabled={!canSave} > {i18n.translate( 'xpack.apm.settings.apmIndices.applyButton', diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx index 4477ee5a99be3..63dd486544124 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx @@ -219,7 +219,8 @@ describe('CustomLink', () => { expect(saveCustomLinkSpy).toHaveBeenCalledTimes(1); }); - it('deletes a custom link', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/75106 + it.skip('deletes a custom link', async () => { const mockContext = getMockAPMContext({ canSave: true }); const component = render( diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/__tests__/ErrorCount.test.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/ErrorCount.test.tsx similarity index 89% rename from x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/__tests__/ErrorCount.test.tsx rename to x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/ErrorCount.test.tsx index 40b8a57f55051..2bfa820ee5e76 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/__tests__/ErrorCount.test.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/ErrorCount.test.tsx @@ -6,8 +6,8 @@ import { fireEvent, render } from '@testing-library/react'; import React from 'react'; -import { expectTextsInDocument } from '../../../../../utils/testHelpers'; -import { ErrorCount } from '../ErrorCount'; +import { expectTextsInDocument } from '../../../../utils/testHelpers'; +import { ErrorCount } from './ErrorCount'; describe('ErrorCount', () => { it('shows singular error message', () => { diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/index.tsx index 1f8ff6fdcaf19..2991264b5c0c1 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/index.tsx @@ -137,9 +137,7 @@ export function getServiceColumns({ field: 'transactionType', name: i18n.translate( 'xpack.apm.servicesTable.transactionColumnLabel', - { - defaultMessage: 'Transaction type', - } + { defaultMessage: 'Transaction type' } ), width: px(unit * 10), sortable: true, @@ -148,12 +146,9 @@ export function getServiceColumns({ : []), { field: 'avgResponseTime', - name: i18n.translate( - 'xpack.apm.servicesTable.avgResponseTimeColumnLabel', - { - defaultMessage: 'Avg. response time', - } - ), + name: i18n.translate('xpack.apm.servicesTable.latencyAvgColumnLabel', { + defaultMessage: 'Latency (avg.)', + }), sortable: true, dataType: 'number', render: (_, { avgResponseTime }) => ( @@ -168,12 +163,9 @@ export function getServiceColumns({ }, { field: 'transactionsPerMinute', - name: i18n.translate( - 'xpack.apm.servicesTable.transactionsPerMinuteColumnLabel', - { - defaultMessage: 'Trans. per minute', - } - ), + name: i18n.translate('xpack.apm.servicesTable.throughputColumnLabel', { + defaultMessage: 'Throughput', + }), sortable: true, dataType: 'number', render: (_, { transactionsPerMinute }) => ( diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/service_list.test.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/service_list.test.tsx index 45a4afeb53235..275ea3aa13a20 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/service_list.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/ServiceList/service_list.test.tsx @@ -76,13 +76,13 @@ describe('ServiceList', () => { expect(healthHeading).toBeNull(); }); - it('sorts by transactions per minute', async () => { + it('sorts by throughput', async () => { const { findByTitle } = renderWithTheme(, { wrapper: Wrapper, }); expect( - await findByTitle('Trans. per minute; Sorted in descending order') + await findByTitle('Throughput; Sorted in descending order') ).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index ae297b840ebc8..6ea1c7f7c5b41 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -102,9 +102,7 @@ export function ServiceOverviewDependenciesTable({ serviceName }: Props) { field: 'throughputValue', name: i18n.translate( 'xpack.apm.serviceOverview.dependenciesTableColumnThroughput', - { - defaultMessage: 'Traffic', - } + { defaultMessage: 'Throughput' } ), width: px(unit * 10), render: (_, { throughput }) => { diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx index 51a4ef649a3ba..a092e572b7332 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/index.tsx @@ -117,9 +117,7 @@ export function ServiceOverviewInstancesTable({ serviceName }: Props) { field: 'throughputValue', name: i18n.translate( 'xpack.apm.serviceOverview.instancesTableColumnThroughput', - { - defaultMessage: 'Traffic', - } + { defaultMessage: 'Throughput' } ), width: px(unit * 10), render: (_, { throughput }) => { diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx index e63d30022360e..b79e011bde488 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx @@ -51,7 +51,7 @@ export function ServiceOverviewThroughputChart({

    {i18n.translate('xpack.apm.serviceOverview.throughtputChartTitle', { - defaultMessage: 'Traffic', + defaultMessage: 'Throughput', })}

    @@ -66,10 +66,8 @@ export function ServiceOverviewThroughputChart({ type: 'linemark', color: theme.eui.euiColorVis0, title: i18n.translate( - 'xpack.apm.serviceOverview.throughputChart.traffic', - { - defaultMessage: 'Traffic', - } + 'xpack.apm.serviceOverview.throughtputChartTitle', + { defaultMessage: 'Throughput' } ), }, ]} diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx index 307997731e5ef..0cb0ec4311043 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx @@ -55,30 +55,29 @@ const DEFAULT_SORT = { function getLatencyAggregationTypeLabel(latencyAggregationType?: string) { switch (latencyAggregationType) { - case 'avg': { - i18n.translate( + case 'avg': + return i18n.translate( 'xpack.apm.serviceOverview.transactionsTableColumnLatency.avg', { defaultMessage: 'Latency (avg.)', } ); - } - case 'p95': { + + case 'p95': return i18n.translate( 'xpack.apm.serviceOverview.transactionsTableColumnLatency.p95', { defaultMessage: 'Latency (95th)', } ); - } - case 'p99': { + + case 'p99': return i18n.translate( 'xpack.apm.serviceOverview.transactionsTableColumnLatency.p99', { defaultMessage: 'Latency (99th)', } ); - } } } @@ -210,10 +209,8 @@ export function ServiceOverviewTransactionsTable(props: Props) { { field: 'throughput', name: i18n.translate( - 'xpack.apm.serviceOverview.transactionsTableColumnTroughput', - { - defaultMessage: 'Traffic', - } + 'xpack.apm.serviceOverview.transactionsTableColumnThroughput', + { defaultMessage: 'Throughput' } ), width: px(unit * 10), render: (_, { throughput }) => { diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx index 1699b7e7474fe..d2a3dc54c2a48 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx @@ -101,10 +101,8 @@ export function TransactionList({ items, isLoading }: Props) { { field: 'transactionsPerMinute', name: i18n.translate( - 'xpack.apm.transactionsTable.transactionsPerMinuteColumnLabel', - { - defaultMessage: 'Trans. per minute', - } + 'xpack.apm.transactionsTable.throughputColumnLabel', + { defaultMessage: 'Throughput' } ), sortable: true, dataType: 'number', diff --git a/x-pack/plugins/apm/public/components/shared/ManagedTable/index.tsx b/x-pack/plugins/apm/public/components/shared/ManagedTable/index.tsx index 6f62fd24e71ea..8033b6415319e 100644 --- a/x-pack/plugins/apm/public/components/shared/ManagedTable/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/ManagedTable/index.tsx @@ -102,8 +102,8 @@ function UnoptimizedManagedTable(props: Props) { ...toQuery(history.location.search), page: options.page.index, pageSize: options.page.size, - sortField: options.sort!.field, - sortDirection: options.sort!.direction, + sortField: options.sort?.field, + sortDirection: options.sort?.direction, }), }); }, diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx index 0a67db0f15b32..a32302d246423 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx @@ -56,7 +56,7 @@ export function CustomLinkMenuSection({ const { data: customLinks = [], status, refetch } = useFetcher( (callApmApi) => callApmApi({ - isCachable: true, + isCachable: false, endpoint: 'GET /api/apm/settings/custom_links', params: { query: convertFiltersToQuery(filters) }, }), diff --git a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx index 506c27051b511..a135bff14d3c6 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx @@ -16,7 +16,6 @@ import { import { GenericMetricsChart } from '../../../../../server/lib/metrics/transform_metrics_chart'; import { Maybe } from '../../../../../typings/common'; import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; -import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; import { TimeseriesChart } from '../timeseries_chart'; function getYTickFormatter(chart: GenericMetricsChart) { @@ -33,15 +32,13 @@ function getYTickFormatter(chart: GenericMetricsChart) { return (y: Maybe) => asPercent(y || 0, 1); } case 'time': { - return (y: Maybe) => asDuration(y); + return asDuration; } case 'integer': { - return (y: Maybe) => - isValidCoordinateValue(y) ? asInteger(y) : y; + return asInteger; } default: { - return (y: Maybe) => - isValidCoordinateValue(y) ? asDecimal(y) : y; + return asDecimal; } } } @@ -63,7 +60,7 @@ export function MetricsChart({ chart, fetchStatus }: Props) { fetchStatus={fetchStatus} id={chart.key} timeseries={chart.series} - yLabelFormat={getYTickFormatter(chart) as (y: number) => string} + yLabelFormat={getYTickFormatter(chart)} /> ); diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/index.tsx index 38a980fbcd90a..bbae0cd61264f 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/index.tsx @@ -26,7 +26,7 @@ export function TransactionBreakdownChart({

    {i18n.translate('xpack.apm.transactionBreakdown.chartTitle', { - defaultMessage: 'Average duration by span type', + defaultMessage: 'Time spent by span type', })}

    diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.test.ts b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.test.ts index e92ecd2aeefd8..6d7e279f47e04 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.test.ts +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.test.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - getResponseTimeTickFormatter, - getResponseTimeTooltipFormatter, - getMaxY, -} from './helper'; +import { getResponseTimeTickFormatter, getMaxY } from './helper'; import { TimeSeries, Coordinate } from '../../../../../typings/timeseries'; import { @@ -25,35 +21,26 @@ describe('transaction chart helper', () => { '1.0 min' ); }); + it('formattes time tick in seconds', () => { const formatter = getDurationFormatter(toMicroseconds(11, 'seconds')); const timeTickFormatter = getResponseTimeTickFormatter(formatter); expect(timeTickFormatter(toMicroseconds(6, 'seconds'))).toEqual('6.0 s'); }); }); - describe('getResponseTimeTooltipFormatter', () => { - const formatter = getDurationFormatter(toMicroseconds(11, 'minutes')); - const tooltipFormatter = getResponseTimeTooltipFormatter(formatter); - it("doesn't format invalid y coordinate", () => { - expect(tooltipFormatter({ x: 1, y: undefined })).toEqual('N/A'); - expect(tooltipFormatter({ x: 1, y: null })).toEqual('N/A'); - }); - it('formattes tooltip in minutes', () => { - expect( - tooltipFormatter({ x: 1, y: toMicroseconds(60, 'seconds') }) - ).toEqual('1.0 min'); - }); - }); + describe('getMaxY', () => { it('returns zero when empty time series', () => { expect(getMaxY([])).toEqual(0); }); + it('returns zero for invalid y coordinate', () => { const timeSeries = ([ { data: [{ x: 1 }, { x: 2 }, { x: 3, y: -1 }] }, ] as unknown) as Array>; expect(getMaxY(timeSeries)).toEqual(0); }); + it('returns the max y coordinate', () => { const timeSeries = ([ { diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.tsx index 4d2a60c494178..a8583b4b0dada 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/helper.tsx @@ -4,23 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n'; -import { TimeFormatter } from '../../../../../common/utils/formatters'; import { Coordinate, TimeSeries } from '../../../../../typings/timeseries'; -import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; +import { TimeFormatter } from '../../../../../common/utils/formatters'; export function getResponseTimeTickFormatter(formatter: TimeFormatter) { - return (t: number) => { - return formatter(t).formatted; - }; -} - -export function getResponseTimeTooltipFormatter(formatter: TimeFormatter) { - return (coordinate: Coordinate) => { - return isValidCoordinateValue(coordinate.y) - ? formatter(coordinate.y).formatted - : NOT_AVAILABLE_LABEL; - }; + return (t: number) => formatter(t).formatted; } export function getMaxY(timeSeries?: Array>) { diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx index 0ea0ee3e5a456..297cf050c4bbc 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx @@ -13,11 +13,9 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { TRANSACTION_REQUEST } from '../../../../../common/transaction_types'; import { asTransactionRate } from '../../../../../common/utils/formatters'; import { AnnotationsContextProvider } from '../../../../context/annotations/annotations_context'; import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; -import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useTransactionThroughputChartsFetcher } from '../../../../hooks/use_transaction_throughput_chart_fetcher'; import { LatencyChart } from '../latency_chart'; import { TimeseriesChart } from '../timeseries_chart'; @@ -25,9 +23,6 @@ import { TransactionBreakdownChart } from '../transaction_breakdown_chart'; import { TransactionErrorRateChart } from '../transaction_error_rate_chart/'; export function TransactionCharts() { - const { urlParams } = useUrlParams(); - const { transactionType } = urlParams; - const { throughputChartsData, throughputChartsStatus, @@ -49,11 +44,16 @@ export function TransactionCharts() { - {tpmLabel(transactionType)} + + {i18n.translate( + 'xpack.apm.metrics.transactionChart.throughputLabel', + { defaultMessage: 'Throughput' } + )} + @@ -76,19 +76,3 @@ export function TransactionCharts() { ); } - -function tpmLabel(type?: string) { - return type === TRANSACTION_REQUEST - ? i18n.translate( - 'xpack.apm.metrics.transactionChart.requestsPerMinuteLabel', - { - defaultMessage: 'Requests per minute', - } - ) - : i18n.translate( - 'xpack.apm.metrics.transactionChart.transactionsPerMinuteLabel', - { - defaultMessage: 'Transactions per minute', - } - ); -} diff --git a/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts b/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts new file mode 100644 index 0000000000000..587cb172eeab7 --- /dev/null +++ b/x-pack/plugins/apm/public/context/url_params_context/helpers.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import datemath from '@elastic/datemath'; +import moment from 'moment-timezone'; +import * as helpers from './helpers'; + +describe('url_params_context helpers', () => { + describe('getParsedDate', () => { + describe('given undefined', () => { + it('returns undefined', () => { + expect(helpers.getParsedDate(undefined)).toBeUndefined(); + }); + }); + + describe('given a parsable date', () => { + it('returns the parsed date', () => { + expect(helpers.getParsedDate('1970-01-01T00:00:00.000Z')).toEqual( + '1970-01-01T00:00:00.000Z' + ); + }); + }); + + describe('given a non-parsable date', () => { + it('returns null', () => { + expect(helpers.getParsedDate('nope')).toEqual(null); + }); + }); + }); + + describe('getDateRange', () => { + describe('when rangeFrom and rangeTo are not changed', () => { + it('returns the previous state', () => { + expect( + helpers.getDateRange({ + state: { + rangeFrom: 'now-1m', + rangeTo: 'now', + start: '1970-01-01T00:00:00.000Z', + end: '1971-01-01T00:00:00.000Z', + }, + rangeFrom: 'now-1m', + rangeTo: 'now', + }) + ).toEqual({ + start: '1970-01-01T00:00:00.000Z', + end: '1971-01-01T00:00:00.000Z', + }); + }); + }); + + describe('when rangeFrom or rangeTo have changed', () => { + it('returns new state', () => { + jest.spyOn(datemath, 'parse').mockReturnValue(moment(0).utc()); + + expect( + helpers.getDateRange({ + state: { + rangeFrom: 'now-1m', + rangeTo: 'now', + start: '1972-01-01T00:00:00.000Z', + end: '1973-01-01T00:00:00.000Z', + }, + rangeFrom: 'now-2m', + rangeTo: 'now', + }) + ).toEqual({ + start: '1970-01-01T00:00:00.000Z', + end: '1970-01-01T00:00:00.000Z', + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/context/url_params_context/helpers.ts b/x-pack/plugins/apm/public/context/url_params_context/helpers.ts index 45db4dcc94cce..bff2ef5deb86c 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/helpers.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/helpers.ts @@ -17,18 +17,23 @@ export function getParsedDate(rawDate?: string, opts = {}) { } } -export function getStart(prevState: IUrlParams, rangeFrom?: string) { - if (prevState.rangeFrom !== rangeFrom) { - return getParsedDate(rangeFrom); +export function getDateRange({ + state, + rangeFrom, + rangeTo, +}: { + state: IUrlParams; + rangeFrom?: string; + rangeTo?: string; +}) { + if (state.rangeFrom === rangeFrom && state.rangeTo === rangeTo) { + return { start: state.start, end: state.end }; } - return prevState.start; -} -export function getEnd(prevState: IUrlParams, rangeTo?: string) { - if (prevState.rangeTo !== rangeTo) { - return getParsedDate(rangeTo, { roundUp: true }); - } - return prevState.end; + return { + start: getParsedDate(rangeFrom), + end: getParsedDate(rangeTo, { roundUp: true }), + }; } export function toNumber(value?: string) { diff --git a/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts b/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts index 6d9f982f92751..0596d649116a0 100644 --- a/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts +++ b/x-pack/plugins/apm/public/context/url_params_context/resolve_url_params.ts @@ -11,8 +11,7 @@ import { pickKeys } from '../../../common/utils/pick_keys'; import { localUIFilterNames } from '../../../server/lib/ui_filters/local_ui_filters/config'; import { toQuery } from '../../components/shared/Links/url_helpers'; import { - getEnd, - getStart, + getDateRange, removeUndefinedProps, toBoolean, toNumber, @@ -56,8 +55,7 @@ export function resolveUrlParams(location: Location, state: TimeUrlParams) { return removeUndefinedProps({ // date params - start: getStart(state, rangeFrom), - end: getEnd(state, rangeTo), + ...getDateRange({ state, rangeFrom, rangeTo }), rangeFrom, rangeTo, refreshPaused: refreshPaused ? toBoolean(refreshPaused) : undefined, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index 62fc16fb25053..6d91e64be034d 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -159,7 +159,7 @@ export async function createApmTelemetry({ logger.debug( `Stored telemetry is out of date. Task will run immediately. Stored: ${currentData.kibanaVersion}, expected: ${kibanaVersion}` ); - taskManagerStart.runNow(APM_TELEMETRY_TASK_NAME); + await taskManagerStart.runNow(APM_TELEMETRY_TASK_NAME); } } catch (err) { if (!SavedObjectsErrorHelpers.isNotFoundError(err)) { diff --git a/x-pack/plugins/canvas/kibana.json b/x-pack/plugins/canvas/kibana.json index 38bbb074f6dbd..c14e8340957ad 100644 --- a/x-pack/plugins/canvas/kibana.json +++ b/x-pack/plugins/canvas/kibana.json @@ -5,7 +5,30 @@ "configPath": ["xpack", "canvas"], "server": true, "ui": true, - "requiredPlugins": ["bfetch", "data", "embeddable", "expressions", "features", "inspector", "uiActions", "charts"], - "optionalPlugins": ["usageCollection", "home"], - "requiredBundles": ["kibanaReact", "maps", "lens", "visualizations", "kibanaUtils", "kibanaLegacy", "discover", "savedObjects", "reporting", "home"] + "requiredPlugins": [ + "bfetch", + "charts", + "data", + "embeddable", + "expressions", + "features", + "inspector", + "uiActions" + ], + "optionalPlugins": [ + "home", + "usageCollection" + ], + "requiredBundles": [ + "discover", + "home", + "kibanaLegacy", + "kibanaReact", + "kibanaUtils", + "lens", + "maps", + "reporting", + "savedObjects", + "visualizations" + ] } diff --git a/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.test.tsx similarity index 82% rename from x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/footer.test.tsx index 9df94127ea51d..254c00f15b375 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.test.tsx @@ -6,11 +6,11 @@ import { mount } from 'enzyme'; import React from 'react'; -import { JestContext } from '../../../test/context_jest'; -import { getScrubber as scrubber, getPageControlsCenter as center } from '../../../test/selectors'; -import { Footer } from '../footer'; +import { JestContext } from '../../test/context_jest'; +import { getScrubber as scrubber, getPageControlsCenter as center } from '../../test/selectors'; +import { Footer } from './footer'; -jest.mock('../../../supported_renderers'); +jest.mock('../../supported_renderers'); describe('