diff --git a/.buildkite/scripts/post_build_kibana.sh b/.buildkite/scripts/post_build_kibana.sh index a4f8d71b77105b..ad22a224f7c554 100755 --- a/.buildkite/scripts/post_build_kibana.sh +++ b/.buildkite/scripts/post_build_kibana.sh @@ -6,7 +6,7 @@ if [[ ! "${DISABLE_CI_STATS_SHIPPING:-}" ]]; then echo "--- Ship Kibana Distribution Metrics to CI Stats" node scripts/ship_ci_stats \ --metrics target/optimizer_bundle_metrics.json \ - --metrics packages/kbn-ui-shared-deps/target/metrics.json + --metrics node_modules/@kbn/ui-shared-deps/shared_built_assets/metrics.json fi echo "--- Upload Build Artifacts" diff --git a/.eslintignore b/.eslintignore index ce21d5bb312649..63cd01d6e90db8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -37,7 +37,7 @@ snapshots.js /packages/kbn-test/src/functional_test_runner/__tests__/fixtures/ /packages/kbn-test/src/functional_test_runner/lib/config/__tests__/fixtures/ /packages/kbn-ui-framework/dist -/packages/kbn-ui-shared-deps/flot_charts +/packages/kbn-ui-shared-deps/src/flot_charts /packages/kbn-monaco/src/painless/antlr # Bazel diff --git a/.eslintrc.js b/.eslintrc.js index 22d0270a5b066b..40dd6a55a2a3f6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -875,6 +875,16 @@ module.exports = { }, }, + /** + * Cases overrides + */ + { + files: ['x-pack/plugins/cases/**/*.{js,mjs,ts,tsx}'], + rules: { + 'no-duplicate-imports': 'error', + }, + }, + /** * Security Solution overrides */ @@ -1461,7 +1471,7 @@ module.exports = { }, }, { - files: ['packages/kbn-ui-shared-deps/flot_charts/**/*.js'], + files: ['packages/kbn-ui-shared-deps/src/flot_charts/**/*.js'], env: { jquery: true, }, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a017c79309a56c..f2d67498130131 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -76,6 +76,7 @@ /src/plugins/apm_oss/ @elastic/apm-ui /src/apm.js @elastic/kibana-core @vigneshshanmugam /packages/kbn-apm-config-loader/ @elastic/kibana-core @vigneshshanmugam +/src/core/types/elasticsearch @elastic/apm-ui #CC# /src/plugins/apm_oss/ @elastic/apm-ui #CC# /x-pack/plugins/observability/ @elastic/apm-ui diff --git a/.i18nrc.json b/.i18nrc.json index ad91042a2172de..0926f737227315 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -11,7 +11,7 @@ "uiActionsExamples": "examples/ui_action_examples", "share": "src/plugins/share", "home": "src/plugins/home", - "flot": "packages/kbn-ui-shared-deps/flot_charts", + "flot": "packages/kbn-ui-shared-deps/src/flot_charts", "charts": "src/plugins/charts", "esUi": "src/plugins/es_ui_shared", "devTools": "src/plugins/dev_tools", diff --git a/dev_docs/best_practices.mdx b/dev_docs/best_practices.mdx index 54aaaa6b9497ad..d87c6eb618993d 100644 --- a/dev_docs/best_practices.mdx +++ b/dev_docs/best_practices.mdx @@ -241,35 +241,136 @@ There are some exceptions where a separate repo makes sense. However, they are e It may be tempting to get caught up in the dream of writing the next package which is published to npm and downloaded millions of times a week. Knowing the quality of developers that are working on Kibana, this is a real possibility. However, knowing which packages will see mass adoption is impossible to predict. Instead of jumping directly to writing code in a separate repo and accepting all of the complications that come along with it, prefer keeping code inside the Kibana repo. A [Kibana package](https://github.com/elastic/kibana/tree/master/packages) can be used to publish a package to npm, while still keeping the code inside the Kibana repo. Move code to an external repo only when there is a good reason, for example to enable external contributions. -## Hardening - -Review the following items related to vulnerability and security risks. - -- XSS - - Check for usages of `dangerouslySetInnerHtml`, `Element.innerHTML`, `Element.outerHTML` - - Ensure all user input is properly escaped. - - Ensure any input in `$.html`, `$.append`, `$.appendTo`, $.prepend`, `$.prependTo`is escaped. Instead use`$.text`, or don't use jQuery at all. -- CSRF - - Ensure all APIs are running inside the Kibana HTTP service. -- RCE - - Ensure no usages of `eval` - - Ensure no usages of dynamic requires - - Check for template injection - - Check for usages of templating libraries, including `_.template`, and ensure that user provided input isn't influencing the template and is only used as data for rendering the template. - - Check for possible prototype pollution. -- Prototype Pollution - more info [here](https://docs.google.com/document/d/19V-d9sb6IF-fbzF4iyiPpAropQNydCnoJApzSX5FdcI/edit?usp=sharing) - - Check for instances of `anObject[a][b] = c` where a, b, and c are user defined. This includes code paths where the following logical code steps could be performed in separate files by completely different operations, or recursively using dynamic operations. - - Validate any user input, including API url-parameters/query-parameters/payloads, preferable against a schema which only allows specific keys/values. At a very minimum, black-list `__proto__` and `prototype.constructor` for use within keys - - When calling APIs which spawn new processes or potentially perform code generation from strings, defensively protect against Prototype Pollution by checking `Object.hasOwnProperty` if the arguments to the APIs originate from an Object. An example is the Code app's [spawnProcess](https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44). - - Common Node.js offenders: `child_process.spawn`, `child_process.exec`, `eval`, `Function('some string')`, `vm.runIn*Context(x)` - - Common Client-side offenders: `eval`, `Function('some string')`, `setTimeout('some string', num)`, `setInterval('some string', num)` -- Check for accidental reveal of sensitive information - - The biggest culprit is errors which contain stack traces or other sensitive information which end up in the HTTP Response -- Checked for Mishandled API requests - - Ensure no sensitive cookies are forwarded to external resources. - - Ensure that all user controllable variables that are used in constructing a URL are escaped properly. This is relevant when using `transport.request` with the Elasticsearch client as no automatic escaping is performed. -- Reverse tabnabbing - https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing - - When there are user controllable links or hard-coded links to third-party domains that specify target="\_blank" or target="\_window", the `a` tag should have the rel="noreferrer noopener" attribute specified. - - Allowing users to input markdown is a common culprit, a custom link renderer should be used -- SSRF - https://www.owasp.org/index.php/Server_Side_Request_Forgery - - All network requests made from the Kibana server should use an explicit configuration or white-list specified in the `kibana.yml` +## Security best practices + +When writing code for Kibana, be sure to follow these best practices to avoid common vulnerabilities. Refer to the included Open Web +Application Security Project (OWASP) references to learn more about these types of attacks. + +### Cross-site Scripting (XSS) + +[_OWASP reference for XSS_](https://owasp.org/www-community/attacks/xss) + +XSS is a class of attacks where malicious scripts are injected into vulnerable websites. Kibana defends against this by using the React +framework to safely encode data that is rendered in pages, the EUI framework to [automatically sanitize +links](https://elastic.github.io/eui/#/navigation/link#link-validation), and a restrictive `Content-Security-Policy` header. + +**Best practices** + +* Check for dangerous functions or assignments that can result in unescaped user input in the browser DOM. Avoid using: + * **React:** [`dangerouslySetInnerHtml`](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml). + * **Browser DOM:** `Element.innerHTML` and `Element.outerHTML`. +* If using the aforementioned unsafe functions or assignments is absolutely necessary, follow [these XSS prevention +rules](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#xss-prevention-rules) to ensure that +user input is not inserted into unsafe locations and that it is escaped properly. +* Use EUI components to build your UI, particularly when rendering `href` links. Otherwise, sanitize user input before rendering links to +ensure that they do not use the `javascript:` protocol. +* Don't use the `eval`, `Function`, and `_.template` functions -- these are restricted by ESLint rules. +* Be careful when using `setTimeout` and `setInterval` in client-side code. If an attacker can manipulate the arguments and pass a string to +one of these, it is evaluated dynamically, which is equivalent to the dangerous `eval` function. + +### Cross-Site Request Forgery (CSRF/XSRF) + +[_OWASP reference for CSRF_](https://owasp.org/www-community/attacks/csrf) + +CSRF is a class of attacks where a user is forced to execute an action on a vulnerable website that they're logged into, usually without +their knowledge. Kibana defends against this by requiring [custom request +headers](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#use-of-custom-request-headers) +for API endpoints. For more information, see [API Request +Headers](https://www.elastic.co/guide/en/kibana/master/api.html#api-request-headers). + +**Best practices** + +* Ensure all HTTP routes are registered with the [Kibana HTTP service](https://www.elastic.co/guide/en/kibana/master/http-service.html) to +take advantage of the custom request header security control. + * Note that HTTP GET requests do **not** require the custom request header; any routes that change data should [adhere to the HTTP +specification and use a different method (PUT, POST, etc.)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) + +### Remote Code Execution (RCE) + +[_OWASP reference for Command Injection_](https://owasp.org/www-community/attacks/Command_Injection), +[_OWASP reference for Code Injection_](https://owasp.org/www-community/attacks/Code_Injection) + +RCE is a class of attacks where an attacker executes malicious code or commands on a vulnerable server. Kibana defends against this by using +ESLint rules to restrict vulnerable functions, and by hooking into or hardening usage of these in third-party dependencies. + +**Best practices** + +* Don't use the `eval`, `Function`, and `_.template` functions -- these are restricted by ESLint rules. +* Don't use dynamic `require`. +* Check for usages of templating libraries. Ensure that user-provided input doesn't influence the template and is used only as data for +rendering the template. +* Take extra caution when spawning child processes with any user input or parameters that are user-controlled. + +### Prototype Pollution + +Prototype Pollution is an attack that is unique to JavaScript environments. Attackers can abuse JavaScript's prototype inheritance to +"pollute" objects in the application, which is often used as a vector for XSS or RCE vulnerabilities. Kibana defends against this by +hardening sensitive functions (such as those exposed by `child_process`), and by requiring validation on all HTTP routes by default. + +**Best practices** + +* Check for instances of `anObject[a][b] = c` where `a`, `b`, and `c` are controlled by user input. This includes code paths where the +following logical code steps could be performed in separate files by completely different operations, or by recursively using dynamic +operations. +* Validate all user input, including API URL parameters, query parameters, and payloads. Preferably, use a schema that only allows specific +keys and values. At a minimum, implement a deny-list that prevents `__proto__` and `prototype.constructor` from being used within object +keys. +* When calling APIs that spawn new processes or perform code generation from strings, protect against Prototype Pollution by checking if +`Object.hasOwnProperty` has arguments to the APIs that originate from an Object. An example is the defunct Code app's +[`spawnProcess`](https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44) +function. + * Common Node.js offenders: `child_process.spawn`, `child_process.exec`, `eval`, `Function('some string')`, `vm.runInContext(x)`, +`vm.runInNewContext(x)`, `vm.runInThisContext()` + * Common client-side offenders: `eval`, `Function('some string')`, `setTimeout('some string', num)`, `setInterval('some string', num)` + +See also: + +* [Prototype pollution: The dangerous and underrated vulnerability impacting JavaScript applications | +portswigger.net](https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications) +* [Prototype pollution attack in NodeJS application | Olivier +Arteau](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf) + +### Server-Side Request Forgery (SSRF) + +[_OWASP reference for SSRF_](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) + +SSRF is a class of attacks where a vulnerable server is forced to make an unintended request, usually to an HTTP API. This is often used as +a vector for information disclosure or injection attacks. + +**Best practices** + +* Ensure that all outbound requests from the Kibana server use hard-coded URLs. +* If user input is used to construct a URL for an outbound request, ensure that an allow-list is used to validate the endpoints and that +user input is escaped properly. Ideally, the allow-list should be set in `kibana.yml`, so only server administrators can change it. + * This is particularly relevant when using `transport.request` with the Elasticsearch client, as no automatic escaping is performed. + * Note that URLs are very hard to validate properly; exact match validation for user input is most preferable, while URL parsing or RegEx +validation should only be used if absolutely necessary. + +### Reverse tabnabbing + +[_OWASP reference for Reverse Tabnabbing_](https://owasp.org/www-community/attacks/Reverse_Tabnabbing) + +Reverse tabnabbing is an attack where a link to a malicious page is used to rewrite a vulnerable parent page. This is often used as a vector +for phishing attacks. Kibana defends against this by using the EUI framework, which automatically adds the `rel` attribute to anchor tags, +buttons, and other vulnerable DOM elements. + +**Best practices** + +* Use EUI components to build your UI whenever possible. Otherwise, ensure that any DOM elements that have an `href` attribute also have the +`rel="noreferrer noopener"` attribute specified. For more information, refer to the [OWASP HTML5 Security Cheat +Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing). +* If using a non-EUI markdown renderer, use a custom link renderer for rendered links. + +### Information disclosure + +Information disclosure is not an attack, but it describes whenever sensitive information is accidentally revealed. This can be configuration +info, stack traces, or other data that the user is not authorized to access. This concern cannot be addressed with a single security +control, but at a high level, Kibana relies on the hapi framework to automatically redact stack traces and detailed error messages in HTTP +5xx response payloads. + +**Best practices** + +* Look for instances where sensitive information might accidentally be revealed, particularly in error messages, in the UI, and URL +parameters that are exposed to users. +* Make sure that sensitive request data is not forwarded to external resources. For example, copying client request headers and using them +to make an another request could accidentally expose the user's credentials. diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc index 272cd524c2c200..ac7cbba6e9933a 100644 --- a/docs/canvas/canvas-function-reference.asciidoc +++ b/docs/canvas/canvas-function-reference.asciidoc @@ -71,7 +71,7 @@ Alias: `condition` [[alterColumn_fn]] === `alterColumn` -Converts between core types, including `string`, `number`, `null`, `boolean`, and `date`, and renames columns. See also <> and <>. +Converts between core types, including `string`, `number`, `null`, `boolean`, and `date`, and renames columns. See also <>, <>, and <>. *Expression syntax* [source,js] @@ -1717,11 +1717,16 @@ Adds a column calculated as the result of other columns. Changes are made only w |=== |Argument |Type |Description +|`id` + +|`string`, `null` +|An optional id of the resulting column. When no id is provided, the id will be looked up from the existing column by the provided name argument. If no column with this name exists yet, a new column with this name and an identical id will be added to the table. + |_Unnamed_ *** Aliases: `column`, `name` |`string` -|The name of the resulting column. +|The name of the resulting column. Names are not required to be unique. |`expression` *** @@ -1729,11 +1734,6 @@ Aliases: `exp`, `fn`, `function` |`boolean`, `number`, `string`, `null` |A Canvas expression that is passed to each row as a single row `datatable`. -|`id` - -|`string`, `null` -|An optional id of the resulting column. When not specified or `null` the name argument is used as id. - |`copyMetaFrom` |`string`, `null` @@ -1808,6 +1808,47 @@ Default: `"throw"` *Returns:* `number` | `boolean` | `null` +[float] +[[mathColumn_fn]] +=== `mathColumn` + +Adds a column by evaluating `TinyMath` on each row. This function is optimized for math, so it performs better than the <> with a <>. +*Accepts:* `datatable` + +[cols="3*^<"] +|=== +|Argument |Type |Description + +|id *** +|`string` +|id of the resulting column. Must be unique. + +|name *** +|`string` +|The name of the resulting column. Names are not required to be unique. + +|_Unnamed_ + +Alias: `expression` +|`string` +|A `TinyMath` expression evaluated on each row. See https://www.elastic.co/guide/en/kibana/current/canvas-tinymath-functions.html. + +|`onError` + +|`string` +|In case the `TinyMath` evaluation fails or returns NaN, the return value is specified by onError. For example, `"null"`, `"zero"`, `"false"`, `"throw"`. When `"throw"`, it will throw an exception, terminating expression execution. + +Default: `"throw"` + +|`copyMetaFrom` + +|`string`, `null` +|If set, the meta object from the specified column id is copied over to the specified target column. Throws an exception if the column doesn't exist +|=== + +*Returns:* `datatable` + + [float] [[metric_fn]] === `metric` @@ -2581,7 +2622,7 @@ Default: `false` [[staticColumn_fn]] === `staticColumn` -Adds a column with the same static value in every row. See also <> and <>. +Adds a column with the same static value in every row. See also <>, <>, and <>. *Accepts:* `datatable` diff --git a/docs/developer/best-practices/security.asciidoc b/docs/developer/best-practices/security.asciidoc index 79ecb082950646..fd83aa1dff49fd 100644 --- a/docs/developer/best-practices/security.asciidoc +++ b/docs/developer/best-practices/security.asciidoc @@ -1,55 +1,135 @@ [[security-best-practices]] == Security best practices -* XSS -** Check for usages of `dangerouslySetInnerHtml`, `Element.innerHTML`, -`Element.outerHTML` -** Ensure all user input is properly escaped. -** Ensure any input in `$.html`, `$.append`, `$.appendTo`, -latexmath:[$.prepend`, `$].prependTo`is escaped. Instead use`$.text`, or -don’t use jQuery at all. -* CSRF -** Ensure all APIs are running inside the {kib} HTTP service. -* RCE -** Ensure no usages of `eval` -** Ensure no usages of dynamic requires -** Check for template injection -** Check for usages of templating libraries, including `_.template`, and -ensure that user provided input isn’t influencing the template and is -only used as data for rendering the template. -** Check for possible prototype pollution. -* Prototype Pollution -** Check for instances of `anObject[a][b] = c` where a, b, and c are -user defined. This includes code paths where the following logical code -steps could be performed in separate files by completely different -operations, or recursively using dynamic operations. -** Validate any user input, including API -url-parameters/query-parameters/payloads, preferable against a schema -which only allows specific keys/values. At a very minimum, black-list -`__proto__` and `prototype.constructor` for use within keys -** When calling APIs which spawn new processes or potentially perform -code generation from strings, defensively protect against Prototype -Pollution by checking `Object.hasOwnProperty` if the arguments to the -APIs originate from an Object. An example is the Code app’s -https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44[spawnProcess]. -*** Common Node.js offenders: `child_process.spawn`, -`child_process.exec`, `eval`, `Function('some string')`, -`vm.runIn*Context(x)` -*** Common Client-side offenders: `eval`, `Function('some string')`, -`setTimeout('some string', num)`, `setInterval('some string', num)` -* Check for accidental reveal of sensitive information -** The biggest culprit is errors which contain stack traces or other -sensitive information which end up in the HTTP Response -* Checked for Mishandled API requests -** Ensure no sensitive cookies are forwarded to external resources. -** Ensure that all user controllable variables that are used in -constructing a URL are escaped properly. This is relevant when using -`transport.request` with the {es} client as no automatic -escaping is performed. -* Reverse tabnabbing - -https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing -** When there are user controllable links or hard-coded links to -third-party domains that specify target="_blank" or target="_window", the a tag should have the rel="noreferrer noopener" attribute specified. -Allowing users to input markdown is a common culprit, a custom link renderer should be used -* SSRF - https://www.owasp.org/index.php/Server_Side_Request_Forgery -All network requests made from the {kib} server should use an explicit configuration or white-list specified in the kibana.yml \ No newline at end of file +When writing code for {kib}, be sure to follow these best practices to avoid common vulnerabilities. Refer to the included Open Web +Application Security Project (OWASP) references to learn more about these types of attacks. + +=== Cross-site Scripting (XSS) === + +https://owasp.org/www-community/attacks/xss[_OWASP reference for XSS_] + +XSS is a class of attacks where malicious scripts are injected into vulnerable websites. {kib} defends against this by using the React +framework to safely encode data that is rendered in pages, the EUI framework to +https://elastic.github.io/eui/#/navigation/link#link-validation[automatically sanitize links], and a restrictive `Content-Security-Policy` +header. + +*Best practices* + +* Check for dangerous functions or assignments that can result in unescaped user input in the browser DOM. Avoid using: +** *React:* https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml[`dangerouslySetInnerHtml`]. +** *Browser DOM:* `Element.innerHTML` and `Element.outerHTML`. +* If using the aforementioned unsafe functions or assignments is absolutely necessary, follow +https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#xss-prevention-rules[these XSS prevention +rules] to ensure that user input is not inserted into unsafe locations and that it is escaped properly. +* Use EUI components to build your UI, particularly when rendering `href` links. Otherwise, sanitize user input before rendering links to +ensure that they do not use the `javascript:` protocol. +* Don't use the `eval`, `Function`, and `_.template` functions -- these are restricted by ESLint rules. +* Be careful when using `setTimeout` and `setInterval` in client-side code. If an attacker can manipulate the arguments and pass a string to +one of these, it is evaluated dynamically, which is equivalent to the dangerous `eval` function. + +=== Cross-Site Request Forgery (CSRF/XSRF) === + +https://owasp.org/www-community/attacks/csrf[_OWASP reference for CSRF_] + +CSRF is a class of attacks where a user is forced to execute an action on a vulnerable website that they're logged into, usually without +their knowledge. {kib} defends against this by requiring +https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#use-of-custom-request-headers[custom +request headers] for API endpoints. For more information, see <>. + +*Best practices* + +* Ensure all HTTP routes are registered with the <> to take advantage of the custom request header +security control. +** Note that HTTP GET requests do *not* require the custom request header; any routes that change data should +https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods[adhere to the HTTP specification and use a different method (PUT, POST, etc.)] + +=== Remote Code Execution (RCE) === + +https://owasp.org/www-community/attacks/Command_Injection[_OWASP reference for Command Injection_], +https://owasp.org/www-community/attacks/Code_Injection[_OWASP reference for Code Injection_] + +RCE is a class of attacks where an attacker executes malicious code or commands on a vulnerable server. {kib} defends against this by using +ESLint rules to restrict vulnerable functions, and by hooking into or hardening usage of these in third-party dependencies. + +*Best practices* + +* Don't use the `eval`, `Function`, and `_.template` functions -- these are restricted by ESLint rules. +* Don't use dynamic `require`. +* Check for usages of templating libraries. Ensure that user-provided input doesn't influence the template and is used only as data for +rendering the template. +* Take extra caution when spawning child processes with any user input or parameters that are user-controlled. + +=== Prototype Pollution === + +Prototype Pollution is an attack that is unique to JavaScript environments. Attackers can abuse JavaScript's prototype inheritance to +"pollute" objects in the application, which is often used as a vector for XSS or RCE vulnerabilities. {kib} defends against this by +hardening sensitive functions (such as those exposed by `child_process`), and by requiring validation on all HTTP routes by default. + +*Best practices* + +* Check for instances of `anObject[a][b] = c` where `a`, `b`, and `c` are controlled by user input. This includes code paths where the +following logical code steps could be performed in separate files by completely different operations, or by recursively using dynamic +operations. +* Validate all user input, including API URL parameters, query parameters, and payloads. Preferably, use a schema that only allows specific +keys and values. At a minimum, implement a deny-list that prevents `__proto__` and `prototype.constructor` from being used within object +keys. +* When calling APIs that spawn new processes or perform code generation from strings, protect against Prototype Pollution by checking if +`Object.hasOwnProperty` has arguments to the APIs that originate from an Object. An example is the defunct Code app's +https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44[`spawnProcess`] +function. +** Common Node.js offenders: `child_process.spawn`, `child_process.exec`, `eval`, `Function('some string')`, `vm.runInContext(x)`, +`vm.runInNewContext(x)`, `vm.runInThisContext()` +** Common client-side offenders: `eval`, `Function('some string')`, `setTimeout('some string', num)`, `setInterval('some string', num)` + +See also: + +* https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications[Prototype +pollution: The dangerous and underrated vulnerability impacting JavaScript applications | portswigger.net] +* https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf[Prototype +pollution attack in NodeJS application | Olivier Arteau] + +=== Server-Side Request Forgery (SSRF) === + +https://owasp.org/www-community/attacks/Server_Side_Request_Forgery[_OWASP reference for SSRF_] + +SSRF is a class of attacks where a vulnerable server is forced to make an unintended request, usually to an HTTP API. This is often used as +a vector for information disclosure or injection attacks. + +*Best practices* + +* Ensure that all outbound requests from the {kib} server use hard-coded URLs. +* If user input is used to construct a URL for an outbound request, ensure that an allow-list is used to validate the endpoints and that +user input is escaped properly. Ideally, the allow-list should be set in `kibana.yml`, so only server administrators can change it. +** This is particularly relevant when using `transport.request` with the {es} client, as no automatic escaping is performed. +** Note that URLs are very hard to validate properly; exact match validation for user input is most preferable, while URL parsing or RegEx +validation should only be used if absolutely necessary. + +=== Reverse tabnabbing === + +https://owasp.org/www-community/attacks/Reverse_Tabnabbing[_OWASP reference for Reverse Tabnabbing_] + +Reverse tabnabbing is an attack where a link to a malicious page is used to rewrite a vulnerable parent page. This is often used as a vector +for phishing attacks. {kib} defends against this by using the EUI framework, which automatically adds the `rel` attribute to anchor tags, +buttons, and other vulnerable DOM elements. + +*Best practices* + +* Use EUI components to build your UI whenever possible. Otherwise, ensure that any DOM elements that have an `href` attribute also have the +`rel="noreferrer noopener"` attribute specified. For more information, refer to the +https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing[OWASP HTML5 Security Cheat +Sheet]. +* If using a non-EUI markdown renderer, use a custom link renderer for rendered links. + +=== Information disclosure === + +Information disclosure is not an attack, but it describes whenever sensitive information is accidentally revealed. This can be configuration +info, stack traces, or other data that the user is not authorized to access. This concern cannot be addressed with a single security +control, but at a high level, {kib} relies on the hapi framework to automatically redact stack traces and detailed error messages in HTTP +5xx response payloads. + +*Best practices* + +* Look for instances where sensitive information might accidentally be revealed, particularly in error messages, in the UI, and URL +parameters that are exposed to users. +* Make sure that sensitive request data is not forwarded to external resources. For example, copying client request headers and using them +to make an another request could accidentally expose the user's credentials. diff --git a/docs/developer/getting-started/monorepo-packages.asciidoc b/docs/developer/getting-started/monorepo-packages.asciidoc index 0ae806618adc5d..c211751c09b49a 100644 --- a/docs/developer/getting-started/monorepo-packages.asciidoc +++ b/docs/developer/getting-started/monorepo-packages.asciidoc @@ -87,6 +87,7 @@ yarn kbn watch-bazel - @kbn/monaco - @kbn/rule-data-utils - @kbn/securitysolution-es-utils +- @kbn/securitysolution-hook-utils - @kbn/securitysolution-io-ts-alerting-types - @kbn/securitysolution-io-ts-list-types - @kbn/securitysolution-io-ts-types @@ -101,5 +102,6 @@ yarn kbn watch-bazel - @kbn/std - @kbn/telemetry-utils - @kbn/tinymath +- @kbn/ui-shared-deps - @kbn/utility-types - @kbn/utils diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 6675a8dd283c9b..96326b739422f8 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -261,52 +261,48 @@ The plugin exposes the static DefaultEditorController class to consume. |The markdown visualization that can be used to place text panels on dashboards. -|{kib-repo}blob/{branch}/src/plugins/vis_type_metric/README.md[visTypeMetric] -|Contains the metric visualization. +|{kib-repo}blob/{branch}/src/plugins/vis_type_metric[visTypeMetric] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/vis_type_pie/README.md[visTypePie] -|Contains the pie chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting. +|{kib-repo}blob/{branch}/src/plugins/vis_type_pie[visTypePie] +|WARNING: Missing README. |{kib-repo}blob/{branch}/src/plugins/vis_type_table/README.md[visTypeTable] |Contains the data table visualization, that allows presenting data in a simple table format. -|{kib-repo}blob/{branch}/src/plugins/vis_type_tagcloud/README.md[visTypeTagcloud] -|Contains the tagcloud visualization. +|{kib-repo}blob/{branch}/src/plugins/vis_type_tagcloud[visTypeTagcloud] +|WARNING: Missing README. |{kib-repo}blob/{branch}/src/plugins/vis_type_timelion/README.md[visTypeTimelion] |Contains the timelion visualization and the timelion backend. -|{kib-repo}blob/{branch}/src/plugins/vis_type_timeseries/README.md[visTypeTimeseries] -|Contains everything around TSVB (the editor, visualizatin implementations and backends). +|{kib-repo}blob/{branch}/src/plugins/vis_type_timeseries[visTypeTimeseries] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/vis_type_vega/README.md[visTypeVega] -|Contains the Vega visualization. +|{kib-repo}blob/{branch}/src/plugins/vis_type_vega[visTypeVega] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/vis_type_vislib/README.md[visTypeVislib] -|Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and -heatmap charts. +|{kib-repo}blob/{branch}/src/plugins/vis_type_vislib[visTypeVislib] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/vis_type_xy/README.md[visTypeXy] -|Contains the new xy-axis chart using the elastic-charts library, which will eventually -replace the vislib xy-axis charts including bar, area, and line. +|{kib-repo}blob/{branch}/src/plugins/vis_type_xy[visTypeXy] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/visualizations/README.md[visualizations] -|Contains most of the visualization infrastructure, e.g. the visualization type registry or the -visualization embeddable. +|{kib-repo}blob/{branch}/src/plugins/visualizations[visualizations] +|WARNING: Missing README. -|{kib-repo}blob/{branch}/src/plugins/visualize/README.md[visualize] -|Contains the visualize application which includes the listing page and the app frame, -which will load the visualization's editor. +|{kib-repo}blob/{branch}/src/plugins/visualize[visualize] +|WARNING: Missing README. |=== diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 9930ab7319f653..d3d76079cdc2a1 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -185,5 +185,18 @@ readonly links: { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index ab8cdea5e4d869..34279cef198bfb 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
}>;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 604cdea1a7fbe6..ac8930c52ac5c3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -165,6 +165,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | | [SavedObjectsExportByObjectOptions](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) | Options for the [export by objects API](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) | | [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) | Options for the [export by type API](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) | +| [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) | | | [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | | [SavedObjectsExportTransformContext](./kibana-plugin-core-server.savedobjectsexporttransformcontext.md) | Context passed down to a [export transform function](./kibana-plugin-core-server.savedobjectsexporttransform.md) | | [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md new file mode 100644 index 00000000000000..f7b96e71c8e53a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [id](./kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md) + +## SavedObjectsExportExcludedObject.id property + +id of the excluded object + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md new file mode 100644 index 00000000000000..4766ae25a936df --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) + +## SavedObjectsExportExcludedObject interface + + +Signature: + +```typescript +export interface SavedObjectsExportExcludedObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md) | string | id of the excluded object | +| [reason](./kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md) | string | optional cause of the exclusion | +| [type](./kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md) | string | type of the excluded object | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md new file mode 100644 index 00000000000000..0adb1ba35e6965 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [reason](./kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md) + +## SavedObjectsExportExcludedObject.reason property + +optional cause of the exclusion + +Signature: + +```typescript +reason?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md new file mode 100644 index 00000000000000..be28ac2d0ffb6d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [type](./kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md) + +## SavedObjectsExportExcludedObject.type property + +type of the excluded object + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md new file mode 100644 index 00000000000000..90432bf6d6705b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) > [excludedObjects](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md) + +## SavedObjectsExportResultDetails.excludedObjects property + +excluded objects details + +Signature: + +```typescript +excludedObjects: SavedObjectsExportExcludedObject[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md new file mode 100644 index 00000000000000..05846e28b9caba --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) > [excludedObjectsCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md) + +## SavedObjectsExportResultDetails.excludedObjectsCount property + +number of objects that were excluded from the export + +Signature: + +```typescript +excludedObjectsCount: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md index d98088c5f45be2..f017f2329170ba 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md @@ -16,6 +16,8 @@ export interface SavedObjectsExportResultDetails | Property | Type | Description | | --- | --- | --- | +| [excludedObjects](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md) | SavedObjectsExportExcludedObject[] | excluded objects details | +| [excludedObjectsCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md) | number | number of objects that were excluded from the export | | [exportedCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.exportedcount.md) | number | number of successfully exported objects | | [missingRefCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.missingrefcount.md) | number | number of missing references | | [missingReferences](./kibana-plugin-core-server.savedobjectsexportresultdetails.missingreferences.md) | Array<{
id: string;
type: string;
}> | missing references details | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md index 50d4c5425e8fd3..2effed1ae9d70e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md @@ -11,7 +11,7 @@ A type's export transform function will be executed once per user-initiated expo Signature: ```typescript -export declare type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; +export declare type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md index 56ebb48707f59c..a1bc99ce8d13dc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md @@ -52,6 +52,6 @@ export class Plugin() { | Property | Type | Description | | --- | --- | --- | | [addClientWrapper](./kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) with the given priority. | -| [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | (type: SavedObjectsType) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | +| [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | <Attributes = any>(type: SavedObjectsType<Attributes>) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | | [setClientFactoryProvider](./kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md index 54e01d3110a2dd..7f74ce4d7bea75 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md @@ -11,7 +11,7 @@ See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdef Signature: ```typescript -registerType: (type: SavedObjectsType) => void; +registerType: (type: SavedObjectsType) => void; ``` ## Example diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md index fbaf58f959075b..d98c553656b1f9 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md @@ -9,5 +9,5 @@ An optional [saved objects management section](./kibana-plugin-core-server.saved Signature: ```typescript -management?: SavedObjectsTypeManagementDefinition; +management?: SavedObjectsTypeManagementDefinition; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md index d882938d731c8c..c3aba5261561ff 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface SavedObjectsType +export interface SavedObjectsType ``` ## Remarks @@ -54,7 +54,7 @@ Example after converting to a multi-namespace (shareable) type in 8.1: Note: migration function(s) can be optionally specified for any of these versions and will not interfere with the conversion process. | | [hidden](./kibana-plugin-core-server.savedobjectstype.hidden.md) | boolean | Is the type hidden by default. If true, repositories will not have access to this type unless explicitly declared as an extraType when creating the repository.See [createInternalRepository](./kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md). | | [indexPattern](./kibana-plugin-core-server.savedobjectstype.indexpattern.md) | string | If defined, the type instances will be stored in the given index instead of the default one. | -| [management](./kibana-plugin-core-server.savedobjectstype.management.md) | SavedObjectsTypeManagementDefinition | An optional [saved objects management section](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) definition for the type. | +| [management](./kibana-plugin-core-server.savedobjectstype.management.md) | SavedObjectsTypeManagementDefinition<Attributes> | An optional [saved objects management section](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) definition for the type. | | [mappings](./kibana-plugin-core-server.savedobjectstype.mappings.md) | SavedObjectsTypeMappingDefinition | The [mapping definition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) for the type. | | [migrations](./kibana-plugin-core-server.savedobjectstype.migrations.md) | SavedObjectMigrationMap | (() => SavedObjectMigrationMap) | An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) or a function returning a map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. | | [name](./kibana-plugin-core-server.savedobjectstype.name.md) | string | The name of the type, which is also used as the internal id. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md index f5488d8f0310d4..75f820d7a8e56b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md @@ -9,5 +9,5 @@ Function returning the url to use to redirect to the editing page of this object Signature: ```typescript -getEditUrl?: (savedObject: SavedObject) => string; +getEditUrl?: (savedObject: SavedObject) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md index 7b31dda402571c..d6d50840aaadb6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md @@ -9,7 +9,7 @@ Function returning the url to use to redirect to this object from the management Signature: ```typescript -getInAppUrl?: (savedObject: SavedObject) => { +getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string; }; diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md index 2f39acc66f451e..75784666ef9632 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md @@ -9,5 +9,5 @@ Function returning the title to display in the management table. If not defined, Signature: ```typescript -getTitle?: (savedObject: SavedObject) => string; +getTitle?: (savedObject: SavedObject) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md new file mode 100644 index 00000000000000..fef178e1d98475 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md @@ -0,0 +1,49 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) > [isExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md) + +## SavedObjectsTypeManagementDefinition.isExportable property + +Optional hook to specify whether an object should be exportable. + +If specified, `isExportable` will be called during export for each of this type's objects in the export, and the ones not matching the predicate will be excluded from the export. + +When implementing both `isExportable` and `onExport`, it is mandatory that `isExportable` returns the same value for an object before and after going though the export transform. E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + +Signature: + +```typescript +isExportable?: SavedObjectsExportablePredicate; +``` + +## Remarks + +`importableAndExportable` must be `true` to specify this property. + +## Example + +Registering a type with a per-object exportability predicate + +```ts +// src/plugins/my_plugin/server/plugin.ts +import { myType } from './saved_objects'; + +export class Plugin() { + setup: (core: CoreSetup) => { + core.savedObjects.registerType({ + ...myType, + management: { + ...myType.management, + isExportable: (object) => { + if (object.attributes.myCustomAttr === 'foo') { + return false; + } + return true; + } + }, + }); + } +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md index e9cc2b12108d65..8c42884eb0b317 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md @@ -9,7 +9,7 @@ Configuration options for the [type](./kibana-plugin-core-server.savedobjectstyp Signature: ```typescript -export interface SavedObjectsTypeManagementDefinition +export interface SavedObjectsTypeManagementDefinition ``` ## Properties @@ -17,11 +17,12 @@ export interface SavedObjectsTypeManagementDefinition | Property | Type | Description | | --- | --- | --- | | [defaultSearchField](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.defaultsearchfield.md) | string | The default search field to use for this type. Defaults to id. | -| [getEditUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md) | (savedObject: SavedObject<any>) => string | Function returning the url to use to redirect to the editing page of this object. If not defined, editing will not be allowed. | -| [getInAppUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md) | (savedObject: SavedObject<any>) => {
path: string;
uiCapabilitiesPath: string;
} | Function returning the url to use to redirect to this object from the management section. If not defined, redirecting to the object will not be allowed. | -| [getTitle](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md) | (savedObject: SavedObject<any>) => string | Function returning the title to display in the management table. If not defined, will use the object's type and id to generate a label. | +| [getEditUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the url to use to redirect to the editing page of this object. If not defined, editing will not be allowed. | +| [getInAppUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md) | (savedObject: SavedObject<Attributes>) => {
path: string;
uiCapabilitiesPath: string;
} | Function returning the url to use to redirect to this object from the management section. If not defined, redirecting to the object will not be allowed. | +| [getTitle](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the title to display in the management table. If not defined, will use the object's type and id to generate a label. | | [icon](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.icon.md) | string | The eui icon name to display in the management table. If not defined, the default icon will be used. | | [importableAndExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.importableandexportable.md) | boolean | Is the type importable or exportable. Defaults to false. | -| [onExport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md) | SavedObjectsExportTransform | An optional export transform function that can be used transform the objects of the registered type during the export process.It can be used to either mutate the exported objects, or add additional objects (of any type) to the export list.See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples. | -| [onImport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md) | SavedObjectsImportHook | An optional [import hook](./kibana-plugin-core-server.savedobjectsimporthook.md) to use when importing given type.Import hooks are executed during the savedObjects import process and allow to interact with the imported objects. See the [hook documentation](./kibana-plugin-core-server.savedobjectsimporthook.md) for more info. | +| [isExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md) | SavedObjectsExportablePredicate<Attributes> | Optional hook to specify whether an object should be exportable.If specified, isExportable will be called during export for each of this type's objects in the export, and the ones not matching the predicate will be excluded from the export.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | +| [onExport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md) | SavedObjectsExportTransform<Attributes> | An optional export transform function that can be used transform the objects of the registered type during the export process.It can be used to either mutate the exported objects, or add additional objects (of any type) to the export list.See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | +| [onImport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md) | SavedObjectsImportHook<Attributes> | An optional [import hook](./kibana-plugin-core-server.savedobjectsimporthook.md) to use when importing given type.Import hooks are executed during the savedObjects import process and allow to interact with the imported objects. See the [hook documentation](./kibana-plugin-core-server.savedobjectsimporthook.md) for more info. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md index 6302b36a73c681..a0d41d2d649676 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md @@ -10,10 +10,12 @@ It can be used to either mutate the exported objects, or add additional objects See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples. +When implementing both `isExportable` and `onExport`, it is mandatory that `isExportable` returns the same value for an object before and after going though the export transform. E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + Signature: ```typescript -onExport?: SavedObjectsExportTransform; +onExport?: SavedObjectsExportTransform; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md index f6634c01c66bad..332247b8eb8e17 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md @@ -11,7 +11,7 @@ Import hooks are executed during the savedObjects import process and allow to in Signature: ```typescript -onImport?: SavedObjectsImportHook; +onImport?: SavedObjectsImportHook; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md index c839dd16d9a475..20d631ff74acac 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md @@ -11,9 +11,9 @@ To only get the visible types (which is the most common use case), use `getVisib Signature: ```typescript -getAllTypes(): SavedObjectsType[]; +getAllTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md index ab8a79c3a84552..1e29e632a6ec32 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md @@ -9,9 +9,9 @@ Return all [types](./kibana-plugin-core-server.savedobjectstype.md) currently re Signature: ```typescript -getImportableAndExportableTypes(): SavedObjectsType[]; +getImportableAndExportableTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md index cfa52882bb89d7..160aadb73cced3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md @@ -9,7 +9,7 @@ Return the [type](./kibana-plugin-core-server.savedobjectstype.md) definition fo Signature: ```typescript -getType(type: string): SavedObjectsType | undefined; +getType(type: string): SavedObjectsType | undefined; ``` ## Parameters @@ -20,5 +20,5 @@ getType(type: string): SavedObjectsType | undefined; Returns: -`SavedObjectsType | undefined` +`SavedObjectsType | undefined` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md index a773c6a0a674fb..05f22dcf7010bc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md @@ -11,9 +11,9 @@ A visible type is a type that doesn't explicitly define `hidden=true` during reg Signature: ```typescript -getVisibleTypes(): SavedObjectsType[]; +getVisibleTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.eskuery.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.eskuery.md index 5d92e348d62760..2cde2b74555851 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.eskuery.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.eskuery.md @@ -10,6 +10,6 @@ esKuery: { nodeTypes: import("../common/es_query/kuery/node_types").NodeTypes; fromKueryExpression: (expression: any, parseOptions?: Partial) => import("../common").KueryNode; - toElasticsearchQuery: (node: import("../common").KueryNode, indexPattern?: import("../common").IIndexPattern | undefined, config?: Record | undefined, context?: Record | undefined) => import("../../kibana_utils/common").JsonObject; + toElasticsearchQuery: (node: import("../common").KueryNode, indexPattern?: import("../common").IIndexPattern | undefined, config?: Record | undefined, context?: Record | undefined) => import("@kbn/common-utils").JsonObject; } ``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.eskuery.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.eskuery.md index 19cb742785e7b2..4b96d8af756f37 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.eskuery.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.eskuery.md @@ -10,6 +10,6 @@ esKuery: { nodeTypes: import("../common/es_query/kuery/node_types").NodeTypes; fromKueryExpression: (expression: any, parseOptions?: Partial) => import("../common").KueryNode; - toElasticsearchQuery: (node: import("../common").KueryNode, indexPattern?: import("../common").IIndexPattern | undefined, config?: Record | undefined, context?: Record | undefined) => import("../../kibana_utils/common").JsonObject; + toElasticsearchQuery: (node: import("../common").KueryNode, indexPattern?: import("../common").IIndexPattern | undefined, config?: Record | undefined, context?: Record | undefined) => import("@kbn/common-utils").JsonObject; } ``` diff --git a/docs/management/connectors/action-types/email.asciidoc b/docs/management/connectors/action-types/email.asciidoc index 719d00c16c932a..bab04b80526743 100644 --- a/docs/management/connectors/action-types/email.asciidoc +++ b/docs/management/connectors/action-types/email.asciidoc @@ -95,6 +95,7 @@ The email connector can send email using many popular SMTP email services. For more information about configuring the email connector to work with different email systems, refer to: +* <> * <> * <> * <> @@ -102,6 +103,29 @@ For more information about configuring the email connector to work with differen For other email servers, you can check the list of well-known services that Nodemailer supports in the JSON file https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json[well-known/services.json]. The properties of the objects in those files — `host`, `port`, and `secure` — correspond to the same email connector configuration properties. A missing `secure` property in the "well-known/services.json" file is considered `false`. Typically, `port: 465` uses `secure: true`, and `port: 25` and `port: 587` use `secure: false`. +[float] +[[elasticcloud]] +==== Sending email from Elastic Cloud + +IMPORTANT: These instructions require you to link:{cloud}/ec-watcher.html#ec-watcher-whitelist[whitelist] the email addresses that notifications get sent first. + +Use the following connector settings to send email from Elastic Cloud: + +Sender:: +`noreply@watcheralert.found.io` + +Host:: +`dockerhost` + +Port:: +`10025` + +Secure:: +Toggle off + +Authentication:: +Toggle off + [float] [[gmail]] ==== Sending email from Gmail diff --git a/docs/management/rollups/create_and_manage_rollups.asciidoc b/docs/management/rollups/create_and_manage_rollups.asciidoc index bc876ab67bc62d..bde2ca472b258c 100644 --- a/docs/management/rollups/create_and_manage_rollups.asciidoc +++ b/docs/management/rollups/create_and_manage_rollups.asciidoc @@ -2,6 +2,7 @@ [[data-rollups]] == Rollup Jobs +experimental::[] A rollup job is a periodic task that aggregates data from indices specified by an index pattern, and then rolls it into a new index. Rollup indices are a good way to diff --git a/docs/settings/task-manager-settings.asciidoc b/docs/settings/task-manager-settings.asciidoc index 12c958c9e86838..87f5b700870ebf 100644 --- a/docs/settings/task-manager-settings.asciidoc +++ b/docs/settings/task-manager-settings.asciidoc @@ -28,6 +28,9 @@ Task Manager runs background tasks by polling for work on an interval. You can | `xpack.task_manager.max_workers` | The maximum number of tasks that this Kibana instance will run simultaneously. Defaults to 10. Starting in 8.0, it will not be possible to set the value greater than 100. + + | `xpack.task_manager.monitored_stats_warn_delayed_task_start_in_seconds` + | The amount of seconds we allow a task to delay before printing a warning server log. Defaults to 60. |=== [float] diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index ddb906f390a2d9..c3c29adcea18f9 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -325,6 +325,9 @@ The time interval policy will rotate the log file every given interval of time. When `includeElasticMapsService` is turned off, only the vector layers configured by <> and the tile layer configured by <> are available in <>. *Default: `true`* +| `map.emsUrl:` + | Specifies the URL of a self hosted <> + | `map.proxyElasticMapsServiceInMaps:` | Set to `true` to proxy all <> Elastic Maps Service requests through the {kib} server. *Default: `false`* diff --git a/docs/siem/images/workflow.png b/docs/siem/images/workflow.png new file mode 100644 index 00000000000000..b71c7b0ace301e Binary files /dev/null and b/docs/siem/images/workflow.png differ diff --git a/docs/siem/siem-ui.asciidoc b/docs/siem/siem-ui.asciidoc index 98f8bc218aa76c..1d07e9038667b0 100644 --- a/docs/siem/siem-ui.asciidoc +++ b/docs/siem/siem-ui.asciidoc @@ -1,102 +1,160 @@ [role="xpack"] [[siem-ui]] -== Using Elastic Security +== Elastic Security Overview -Elastic Security is a highly interactive workspace designed for security -analysts. It provides a clear overview of events and alerts from your -environment, and you can use the interactive UI to drill down into areas of -interest. +Elastic Security combines SIEM threat detection features with endpoint +prevention and response capabilities in one solution. These analytical and +protection capabilities, leveraged by the speed and extensibility of +Elasticsearch, enable analysts to defend their organization from threats before +damage and loss occur. -[float] -[[hosts-ui]] -=== Hosts +Elastic Security provides the following security benefits and capabilities: -The Hosts page provides key metrics regarding host-related security events, and -data tables and histograms that let you interact with the Timeline Event Viewer. -You can drill down for deeper insights, and drag and drop items of interest from -the Hosts page to Timeline for further investigation. +* A detection engine to identify attacks and system misconfigurations +* A workspace for event triage and investigations +* Interactive visualizations to investigate process relationships +* Inbuilt case management with automated actions +* Detection of signatureless attacks with prebuilt machine learning anomaly jobs +and detection rules -[role="screenshot"] -image::siem/images/hosts-ui.png[] - - -[float] -[[network-ui]] -=== Network - -The Network page displays key network activity metrics in an interactive map, -and provides network event tables that enable interaction with Timeline. - -[role="screenshot"] -image::siem/images/network-ui.png[] - -[float] -[[detections-ui]] -=== Detections (beta) - -The Detections feature automatically searches for threats and creates -alerts when they are detected. Detection rules define the conditions -for when alerts are created. Elastic Security comes with prebuilt rules that -search for suspicious activity on your network and hosts. Additionally, you can -create your own rules. - -See {security-guide}/detection-engine-overview.html[Detections] for information -on managing detection rules and alerts. - -[role="screenshot"] -image::siem/images/detections-ui.png[] - -[float] -[[cases-ui]] -=== Cases (beta) - -Cases are used to open and track security issues directly in Elastic Security. -Cases list the original reporter and all users who contribute to a case -(`participants`). Case comments support Markdown syntax, and allow linking to -saved Timelines. Additionally, you can send cases to external systems from -within Elastic Security. +[discrete] +== Elastic Security components and workflow -For information about opening, updating, and closing cases, see -{security-guide}/cases-overview.html[Cases] in the Elastic Security Guide. +The following diagram provides a comprehensive illustration of the Elastic Security workflow. [role="screenshot"] -image::siem/images/cases-ui.png[] - -[float] -[[timelines-ui]] -=== Timeline - -Timeline is your workspace for threat hunting and alert investigations. - -[role="screenshot"] -image::siem/images/timeline-ui.png[Elastic Security Timeline] - -You can drag objects of interest into the Timeline Event Viewer to create -exactly the query filter you need. You can drag items from table widgets within -Hosts and Network pages, or even from within Timeline itself. - -A timeline is responsive and persists as you move through Elastic Security -collecting data. - -For detailed information about Timeline, see -{security-guide}/timelines-ui.html[Investigating events in Timeline]. - -[float] -[[sample-workflow]] -=== Sample workflow - -An analyst notices a suspicious user ID that warrants further investigation, and -clicks a URL that links to Elastic Security. - -The analyst uses the tables, histograms, and filtering and search capabilities in -Elastic Security to get to the bottom of the alert. The analyst can drag items of -interest to Timeline for further analysis. - -Within Timeline, the analyst can investigate further - drilling down, -searching, and filtering - and add notes and pin items of interest. - -The analyst can name the timeline, write summary notes, and share it with others -if appropriate. +image::../siem/images/workflow.png[Elastic Security workflow] + +Here's an overview of the flow and its components: + +* Data is shipped from your hosts to {es} via beat modules and the Elastic https://www.elastic.co/endpoint-security/[Endpoint Security agent integration]. This integration provides capabilities such as collecting events, detecting and preventing {security-guide}/detection-engine-overview.html#malware-prevention[malicious activity], and artifact delivery. The {fleet-guide}/fleet-overview.html[{fleet}] app is used to +install and manage agents and integrations on your hosts. ++ +The Endpoint Security integration ships the following data sets: ++ +*** *Windows*: Process, network, file, DNS, registry, DLL and driver loads, +malware security detections +*** *Linux/macOS*: Process, network, file ++ +* https://www.elastic.co/integrations?solution=security[Beat modules]: {beats} +are lightweight data shippers. Beat modules provide a way of collecting and +parsing specific data sets from common sources, such as cloud and OS events, +logs, and metrics. Common security-related modules are listed {security-guide}/ingest-data.html#enable-beat-modules[here]. +* The {security-app} in {kib} is used to manage the *Detection engine*, +*Cases*, and *Timeline*, as well as administer hosts running Endpoint Security: +** Detection engine: Automatically searches for suspicious host and network +activity via the following: +*** {security-guide}/detection-engine-overview.html#detection-engine-overview[Detection rules]: Periodically search the data +({es} indices) sent from your hosts for suspicious events. When a suspicious +event is discovered, a detection alert is generated. External systems, such as +Slack and email, can be used to send notifications when alerts are generated. +You can create your own rules and make use of our {security-guide}/prebuilt-rules.html[prebuilt ones]. +*** {security-guide}/detections-ui-exceptions.html[Exceptions]: Reduce noise and the number of +false positives. Exceptions are associated with rules and prevent alerts when +an exception's conditions are met. *Value lists* contain source event +values that can be used as part of an exception's conditions. When +Elastic {endpoint-sec} is installed on your hosts, you can add malware exceptions +directly to the endpoint from the Security app. +*** {security-guide}/machine-learning.html#included-jobs[{ml-cap} jobs]: Automatic anomaly detection of host and +network events. Anomaly scores are provided per host and can be used with +detection rules. +** {security-guide}/timelines-ui.html[Timeline]: Workspace for investigating alerts and events. +Timelines use queries and filters to drill down into events related to +a specific incident. Timeline templates are attached to rules and use predefined +queries when alerts are investigated. Timelines can be saved and shared with +others, as well as attached to Cases. +** {security-guide}/cases-overview.html[Cases]: An internal system for opening, tracking, and sharing +security issues directly in the Security app. Cases can be integrated with +external ticketing systems. +** {security-guide}/admin-page-ov.html[Administration]: View and manage hosts running {endpoint-sec}. + +{security-guide}/ingest-data.html[Ingest data to Elastic Security] and {security-guide}/install-endpoint.html[Configure and install the Elastic Endpoint integration] describe how to ship security-related +data to {es}. + + +For more background information, see: + +* https://www.elastic.co/products/elasticsearch[{es}]: A real-time, +distributed storage, search, and analytics engine. {es} excels at indexing +streams of semi-structured data, such as logs or metrics. +* https://www.elastic.co/products/kibana[{kib}]: An open-source analytics and +visualization platform designed to work with {es}. You use {kib} to search, +view, and interact with data stored in {es} indices. You can easily compile +advanced data analysis and visualize your data in a variety of charts, tables, +and maps. + +[discrete] +=== Compatibility with cold tier nodes + +Cold tier is a {ref}/data-tiers.html[data tier] that holds time series data that is accessed only occasionally. In {stack} version >=7.11.0, {elastic-sec} supports cold tier data for the following {es} indices: + +* Index patterns specified in `securitySolution:defaultIndex` +* Index patterns specified in the definitions of detection rules, except for indicator match rules +* Index patterns specified in the data sources selector on various {security-app} pages + +{elastic-sec} does NOT support cold tier data for the following {es} indices: + +* Index patterns controlled by {elastic-sec}, including signals and list indices +* Index patterns specified in indicator match rules + +Using cold tier data for unsupported indices may result in detection rule timeouts and overall performance degradation. + +[discrete] +[[self-protection]] +==== Elastic Endpoint self-protection + +Self-protection means that {elastic-endpoint} has guards against users and attackers that may try to interfere with its functionality. This protection feature is consistently enhanced to prevent attackers who may attempt to use newer, more sophisticated tactics to interfere with the {elastic-endpoint}. Self-protection is enabled by default when {elastic-endpoint} installs on supported platforms, listed below. + +Self-protection is enabled on the following 64-bit Windows versions: + +* Windows 8.1 +* Windows 10 +* Windows Server 2012 R2 +* Windows Server 2016 +* Windows Server 2019 + +And on the following macOS versions: + +* macOS 10.15 (Catalina) +* macOS 11 (Big Sur) + +NOTE: Other Windows and macOS variants (and all Linux distributions) do not have self-protection. + +For {stack} version >= 7.11.0, self-protection defines the following permissions: + +* Users -- even Administrator/root -- *cannot* delete {elastic-endpoint} files (located at `c:\Program Files\Elastic\Endpoint` on Windows, and `/Library/Elastic/Endpoint` on macOS). +* Users *cannot* terminate the {elastic-endpoint} program or service. +* Administrator/root users *can* read the endpoint's files. On Windows, the easiest way to read Endpoint files is to start an Administrator `cmd.exe` prompt. On macOS, an Administrator can use the `sudo` command. +* Administrator/root users *can* stop the {elastic-agent}'s service. On Windows, run the `sc stop "Elastic Agent"` command. On macOS, run the `sudo launchctl stop elastic-agent` command. + + +[discrete] +[[siem-integration]] +=== Integration with other Elastic products + +You can use {elastic-sec} with other Elastic products and features to help you +identify and investigate suspicious activity: + +* https://www.elastic.co/products/stack/machine-learning[{ml-cap}] +* https://www.elastic.co/products/stack/alerting[Alerting] +* https://www.elastic.co/products/stack/canvas[Canvas] + +[discrete] +[[data-sources]] +=== APM transaction data sources + +By default, {elastic-sec} monitors {apm-app-ref}/apm-getting-started.html[APM] +`apm-*-transaction*` indices. To add additional APM indices, update the +index patterns in the `securitySolution:defaultIndex` setting ({kib} -> Stack Management -> Advanced Settings -> `securitySolution:defaultIndex`). +[discrete] +[[ecs-compliant-reqs]] +=== ECS compliance data requirements +The {ecs-ref}[Elastic Common Schema (ECS)] defines a common set of fields to be used for +storing event data in Elasticsearch. ECS helps users normalize their event data +to better analyze, visualize, and correlate the data represented in their +events. {elastic-sec} supports events and indicator index data from any ECS-compliant data source. +IMPORTANT: {elastic-sec} requires {ecs-ref}[ECS-compliant data]. If you use third-party data collectors to ship data to {es}, the data must be mapped to ECS. +{security-guide}/siem-field-reference.html[Elastic Security ECS field reference] lists ECS fields used in {elastic-sec}. diff --git a/docs/user/dashboard/aggregation-reference.asciidoc b/docs/user/dashboard/aggregation-reference.asciidoc index 001114578a1cd0..cb5c484def3b9d 100644 --- a/docs/user/dashboard/aggregation-reference.asciidoc +++ b/docs/user/dashboard/aggregation-reference.asciidoc @@ -190,8 +190,8 @@ For information about {es} metrics aggregations, refer to {ref}/search-aggregati | Metrics with filters | -^| X | +^| X | | Average diff --git a/docs/user/dashboard/images/lens_time_shift.png b/docs/user/dashboard/images/lens_time_shift.png new file mode 100644 index 00000000000000..f7edf80bdd0d6c Binary files /dev/null and b/docs/user/dashboard/images/lens_time_shift.png differ diff --git a/docs/user/dashboard/lens-advanced.asciidoc b/docs/user/dashboard/lens-advanced.asciidoc index e49db0c0d026dc..ec8d90aa4920ec 100644 --- a/docs/user/dashboard/lens-advanced.asciidoc +++ b/docs/user/dashboard/lens-advanced.asciidoc @@ -295,6 +295,41 @@ image::images/lens_advanced_5_2.png[Line chart with cumulative sum of orders mad . Click *Save and return*. +[discrete] +[[compare-time-ranges]] +=== Compare time ranges + +*Lens* allows you to compare the currently selected time range with historical data using the *Time shift* option. + +Time shifts can be used on any metric. The special shift *previous* will show the time window preceding the currently selected one, spanning the same duration. +For example, if *Last 7 days* is selected in the time filter, *previous* will show data from 14 days ago to 7 days ago. + +If multiple time shifts are used in a single chart, a multiple of the date histogram interval should be chosen - otherwise data points might not line up in the chart and empty spots can occur. +For example, if a daily interval is used, shifting one series by *36h*, and another one by *1d*, is not recommended. In this scenario, either reduce the interval to *12h*, or create two separate charts. + +To compare current sales numbers with sales from a week ago, follow these steps: + +. Open *Lens*. + +. From the *Chart Type* dropdown, select *Line*. + +. From the *Available fields* list, drag and drop *Records* to the visualization builder. + +. Copy the *Count of Records* series by dragging it to the empty drop target of the *Vertical axis* dimension group (*Drop a field or click to add*) + +. Shift the second *Count of Records* series by one week to do a week-over-week comparison + +.. Click the new *Count of Records [1]* dimension + +.. Click *Add advanced options* below the field selector + +.. Click *Time shift* + +.. Click the *1 week* option. You can also define custom shifts by typing amount followed by time unit (like *1w* for a one week shift), then hit enter. + +[role="screenshot"] +image::images/lens_time_shift.png[Line chart with week-over-week sales comparison] + [discrete] [[view-customers-over-time-by-continents]] === View table of customers by category over time diff --git a/docs/user/dashboard/lens.asciidoc b/docs/user/dashboard/lens.asciidoc index 7927489c596d77..4ecfcc92501228 100644 --- a/docs/user/dashboard/lens.asciidoc +++ b/docs/user/dashboard/lens.asciidoc @@ -315,3 +315,22 @@ Pagination in a data table is unsupported in *Lens*. However, the </packages/kbn-common-utils'], +}; diff --git a/packages/kbn-common-utils/package.json b/packages/kbn-common-utils/package.json new file mode 100644 index 00000000000000..db99f4d6afb985 --- /dev/null +++ b/packages/kbn-common-utils/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/common-utils", + "main": "./target/index.js", + "browser": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "private": true +} \ No newline at end of file diff --git a/src/plugins/discover/public/application/angular/context/query/index.ts b/packages/kbn-common-utils/src/index.ts similarity index 76% rename from src/plugins/discover/public/application/angular/context/query/index.ts rename to packages/kbn-common-utils/src/index.ts index 70e3dc16004720..1b8bffe4bf1580 100644 --- a/src/plugins/discover/public/application/angular/context/query/index.ts +++ b/packages/kbn-common-utils/src/index.ts @@ -6,5 +6,4 @@ * Side Public License, v 1. */ -export { QueryActionsProvider } from './actions'; -export { createInitialLoadingStatusState } from './state'; +export * from './json'; diff --git a/src/plugins/discover/public/application/angular/context/query_parameters/index.ts b/packages/kbn-common-utils/src/json/index.ts similarity index 63% rename from src/plugins/discover/public/application/angular/context/query_parameters/index.ts rename to packages/kbn-common-utils/src/json/index.ts index 2be8d8d9b81e25..96c94df1bb48eb 100644 --- a/src/plugins/discover/public/application/angular/context/query_parameters/index.ts +++ b/packages/kbn-common-utils/src/json/index.ts @@ -6,6 +6,4 @@ * Side Public License, v 1. */ -export { getQueryParameterActions } from './actions'; -export { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE, QUERY_PARAMETER_KEYS } from './constants'; -export { createInitialQueryParametersState } from './state'; +export { JsonArray, JsonValue, JsonObject } from './typed_json'; diff --git a/src/plugins/kibana_utils/common/typed_json.ts b/packages/kbn-common-utils/src/json/typed_json.ts similarity index 100% rename from src/plugins/kibana_utils/common/typed_json.ts rename to packages/kbn-common-utils/src/json/typed_json.ts diff --git a/packages/kbn-common-utils/tsconfig.json b/packages/kbn-common-utils/tsconfig.json new file mode 100644 index 00000000000000..98f1b30c0d7ff2 --- /dev/null +++ b/packages/kbn-common-utils/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "incremental": true, + "outDir": "target", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "sourceRoot": "../../../../packages/kbn-common-utils/src", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts index dbc455bbd2f8fc..24a1de10b2b1df 100644 --- a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts +++ b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts @@ -22,9 +22,8 @@ export async function emptyKibanaIndexAction({ kbnClient: KbnClient; }) { const stats = createStats('emptyKibanaIndex', log); - const kibanaPluginIds = await kbnClient.plugins.getEnabledIds(); - await cleanKibanaIndices({ client, stats, log, kibanaPluginIds }); + await cleanKibanaIndices({ client, stats, log }); await migrateKibanaIndex(kbnClient); stats.createdIndex('.kibana'); return stats.toJSON(); diff --git a/packages/kbn-es-archiver/src/actions/unload.ts b/packages/kbn-es-archiver/src/actions/unload.ts index d8bc013b40991b..98bae36095b880 100644 --- a/packages/kbn-es-archiver/src/actions/unload.ts +++ b/packages/kbn-es-archiver/src/actions/unload.ts @@ -37,7 +37,6 @@ export async function unloadAction({ }) { const name = relative(REPO_ROOT, inputDir); const stats = createStats(name, log); - const kibanaPluginIds = await kbnClient.plugins.getEnabledIds(); const files = prioritizeMappings(await readDirectory(inputDir)); for (const filename of files) { @@ -47,7 +46,7 @@ export async function unloadAction({ createReadStream(resolve(inputDir, filename)) as Readable, ...createParseArchiveStreams({ gzip: isGzip(filename) }), createFilterRecordsStream('index'), - createDeleteIndexStream(client, stats, log, kibanaPluginIds), + createDeleteIndexStream(client, stats, log), ] as [Readable, ...Writable[]]); } diff --git a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.test.ts b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.test.ts index 3198ba86207f04..241d4a89445460 100644 --- a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.test.ts +++ b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.test.ts @@ -28,7 +28,7 @@ describe('esArchiver: createDeleteIndexStream()', () => { await createPromiseFromStreams([ createListStream([createStubIndexRecord('index1')]), - createDeleteIndexStream(client, stats, log, []), + createDeleteIndexStream(client, stats, log), ]); sinon.assert.notCalled(stats.deletedIndex as sinon.SinonSpy); @@ -43,7 +43,7 @@ describe('esArchiver: createDeleteIndexStream()', () => { await createPromiseFromStreams([ createListStream([createStubIndexRecord('index1')]), - createDeleteIndexStream(client, stats, log, []), + createDeleteIndexStream(client, stats, log), ]); sinon.assert.calledOnce(stats.deletedIndex as sinon.SinonSpy); diff --git a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts index e1552b5ed1e3b2..7765419bb9d15e 100644 --- a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts +++ b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts @@ -14,12 +14,7 @@ import { Stats } from '../stats'; import { deleteIndex } from './delete_index'; import { cleanKibanaIndices } from './kibana_index'; -export function createDeleteIndexStream( - client: KibanaClient, - stats: Stats, - log: ToolingLog, - kibanaPluginIds: string[] -) { +export function createDeleteIndexStream(client: KibanaClient, stats: Stats, log: ToolingLog) { return new Transform({ readableObjectMode: true, writableObjectMode: true, @@ -29,7 +24,7 @@ export function createDeleteIndexStream( const { index } = record.value; if (index.startsWith('.kibana')) { - await cleanKibanaIndices({ client, stats, log, kibanaPluginIds }); + await cleanKibanaIndices({ client, stats, log }); } else { await deleteIndex({ client, stats, log, index }); } diff --git a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts index 0712d2789a91ae..635e4324688466 100644 --- a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts +++ b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts @@ -96,21 +96,11 @@ export async function cleanKibanaIndices({ client, stats, log, - kibanaPluginIds, }: { client: KibanaClient; stats: Stats; log: ToolingLog; - kibanaPluginIds: string[]; }) { - if (!kibanaPluginIds.includes('spaces')) { - return await deleteKibanaIndices({ - client, - stats, - log, - }); - } - while (true) { const resp = await client.deleteByQuery( { diff --git a/packages/kbn-monaco/src/esql/index.ts b/packages/kbn-monaco/src/esql/index.ts index a3f9df00118b73..4b50a222ad2d6e 100644 --- a/packages/kbn-monaco/src/esql/index.ts +++ b/packages/kbn-monaco/src/esql/index.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ +import { LangModule as LangModuleType } from '../types'; import { ID } from './constants'; import { lexerRules } from './lexer_rules'; -export const EsqlLang = { ID, lexerRules }; +export const EsqlLang: LangModuleType = { ID, lexerRules }; diff --git a/packages/kbn-monaco/src/helpers.ts b/packages/kbn-monaco/src/helpers.ts new file mode 100644 index 00000000000000..e525b8c1321329 --- /dev/null +++ b/packages/kbn-monaco/src/helpers.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { monaco } from './monaco_imports'; +import { LangModule as LangModuleType } from './types'; + +function registerLanguage(language: LangModuleType) { + const { ID, lexerRules, languageConfiguration } = language; + + monaco.languages.register({ id: ID }); + monaco.languages.setMonarchTokensProvider(ID, lexerRules); + if (languageConfiguration) { + monaco.languages.setLanguageConfiguration(ID, languageConfiguration); + } +} + +export { registerLanguage }; diff --git a/packages/kbn-monaco/src/index.ts b/packages/kbn-monaco/src/index.ts index ce35d7c3572e6c..85d3518461a493 100644 --- a/packages/kbn-monaco/src/index.ts +++ b/packages/kbn-monaco/src/index.ts @@ -12,7 +12,13 @@ import './register_globals'; export { monaco } from './monaco_imports'; export { XJsonLang } from './xjson'; export { PainlessLang, PainlessContext, PainlessAutocompleteField } from './painless'; - /* eslint-disable-next-line @kbn/eslint/module_migration */ import * as BarePluginApi from 'monaco-editor/esm/vs/editor/editor.api'; -export { BarePluginApi }; + +import { registerLanguage } from './helpers'; +import { + LangModule as LangModuleType, + CompleteLangModule as CompleteLangModuleType, +} from './types'; + +export { BarePluginApi, registerLanguage, LangModuleType, CompleteLangModuleType }; diff --git a/packages/kbn-monaco/src/painless/index.ts b/packages/kbn-monaco/src/painless/index.ts index 68582097564308..9863204117b120 100644 --- a/packages/kbn-monaco/src/painless/index.ts +++ b/packages/kbn-monaco/src/painless/index.ts @@ -9,8 +9,9 @@ import { ID } from './constants'; import { lexerRules, languageConfiguration } from './lexer_rules'; import { getSuggestionProvider, getSyntaxErrors } from './language'; +import { CompleteLangModule as CompleteLangModuleType } from '../types'; -export const PainlessLang = { +export const PainlessLang: CompleteLangModuleType = { ID, getSuggestionProvider, lexerRules, diff --git a/packages/kbn-monaco/src/register_globals.ts b/packages/kbn-monaco/src/register_globals.ts index 4047ddedeca42d..c6eb68b89e7184 100644 --- a/packages/kbn-monaco/src/register_globals.ts +++ b/packages/kbn-monaco/src/register_globals.ts @@ -10,6 +10,8 @@ import { XJsonLang } from './xjson'; import { PainlessLang } from './painless'; import { EsqlLang } from './esql'; import { monaco } from './monaco_imports'; +import { registerLanguage } from './helpers'; + // @ts-ignore import xJsonWorkerSrc from '!!raw-loader!../../target_web/xjson.editor.worker.js'; // @ts-ignore @@ -20,14 +22,9 @@ import painlessWorkerSrc from '!!raw-loader!../../target_web/painless.editor.wor /** * Register languages and lexer rules */ -monaco.languages.register({ id: XJsonLang.ID }); -monaco.languages.setMonarchTokensProvider(XJsonLang.ID, XJsonLang.lexerRules); -monaco.languages.setLanguageConfiguration(XJsonLang.ID, XJsonLang.languageConfiguration); -monaco.languages.register({ id: PainlessLang.ID }); -monaco.languages.setMonarchTokensProvider(PainlessLang.ID, PainlessLang.lexerRules); -monaco.languages.setLanguageConfiguration(PainlessLang.ID, PainlessLang.languageConfiguration); -monaco.languages.register({ id: EsqlLang.ID }); -monaco.languages.setMonarchTokensProvider(EsqlLang.ID, EsqlLang.lexerRules); +registerLanguage(XJsonLang); +registerLanguage(PainlessLang); +registerLanguage(EsqlLang); /** * Create web workers by language ID diff --git a/packages/kbn-monaco/src/types.ts b/packages/kbn-monaco/src/types.ts new file mode 100644 index 00000000000000..f977ada5b624b4 --- /dev/null +++ b/packages/kbn-monaco/src/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { monaco } from './monaco_imports'; + +export interface LangModule { + ID: string; + lexerRules: monaco.languages.IMonarchLanguage; + languageConfiguration?: monaco.languages.LanguageConfiguration; + getSuggestionProvider?: Function; + getSyntaxErrors?: Function; +} + +export interface CompleteLangModule extends LangModule { + languageConfiguration: monaco.languages.LanguageConfiguration; + getSuggestionProvider: Function; + getSyntaxErrors: Function; +} diff --git a/packages/kbn-monaco/src/xjson/index.ts b/packages/kbn-monaco/src/xjson/index.ts index 5e278795fef128..e9ece97ac00234 100644 --- a/packages/kbn-monaco/src/xjson/index.ts +++ b/packages/kbn-monaco/src/xjson/index.ts @@ -12,5 +12,6 @@ import './language'; import { ID } from './constants'; import { lexerRules, languageConfiguration } from './lexer_rules'; +import { LangModule as LangModuleType } from '../types'; -export const XJsonLang = { ID, lexerRules, languageConfiguration }; +export const XJsonLang: LangModuleType = { ID, lexerRules, languageConfiguration }; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 9b4199c8128644..9adc075a7983f8 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -108,6 +108,6 @@ pageLoadAssetSize: banners: 17946 mapsEms: 26072 timelines: 28613 - cases: 162385 screenshotMode: 17856 visTypePie: 35583 + cases: 144442 diff --git a/packages/kbn-optimizer/package.json b/packages/kbn-optimizer/package.json index 54fcdc3bb130ff..a6c8284ad15f64 100644 --- a/packages/kbn-optimizer/package.json +++ b/packages/kbn-optimizer/package.json @@ -9,8 +9,5 @@ "build": "../../node_modules/.bin/tsc", "kbn:bootstrap": "yarn build", "kbn:watch": "yarn build --watch" - }, - "dependencies": { - "@kbn/ui-shared-deps": "link:../kbn-ui-shared-deps" } } \ No newline at end of file diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index 50c9e7e12904f7..97a7f33be673d0 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -15,7 +15,7 @@ import cpy from 'cpy'; import del from 'del'; import { tap, filter } from 'rxjs/operators'; import { REPO_ROOT } from '@kbn/utils'; -import { ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog, createReplaceSerializer } from '@kbn/dev-utils'; import { runOptimizer, OptimizerConfig, OptimizerUpdate, logOptimizerState } from '../index'; import { allValuesFrom } from '../common'; @@ -29,6 +29,8 @@ expect.addSnapshotSerializer({ test: (value: any) => typeof value === 'string' && value.includes(REPO_ROOT), }); +expect.addSnapshotSerializer(createReplaceSerializer(/\w+-fastbuild/, '-fastbuild')); + const log = new ToolingLog({ level: 'error', writeTo: { @@ -130,13 +132,13 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { expect(foo.cache.getModuleCount()).toBe(6); expect(foo.cache.getReferencedFiles()).toMatchInlineSnapshot(` Array [ + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/bazel-out/-fastbuild/bin/packages/kbn-ui-shared-deps/target/public_path_module_creator.js, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/kibana.json, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/async_import.ts, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/ext.ts, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/index.ts, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo/public/lib.ts, /packages/kbn-optimizer/src/worker/entry_point_creator.ts, - /packages/kbn-ui-shared-deps/public_path_module_creator.js, ] `); @@ -153,6 +155,7 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { /node_modules/@kbn/optimizer/postcss.config.js, /node_modules/css-loader/package.json, /node_modules/style-loader/package.json, + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/bazel-out/-fastbuild/bin/packages/kbn-ui-shared-deps/target/public_path_module_creator.js, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/kibana.json, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/index.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/index.ts, @@ -162,7 +165,6 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss, /packages/kbn-optimizer/src/worker/entry_point_creator.ts, - /packages/kbn-ui-shared-deps/public_path_module_creator.js, ] `); @@ -173,10 +175,10 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { expect(baz.cache.getReferencedFiles()).toMatchInlineSnapshot(` Array [ + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/bazel-out/-fastbuild/bin/packages/kbn-ui-shared-deps/target/public_path_module_creator.js, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/x-pack/baz/kibana.json, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/x-pack/baz/public/index.ts, /packages/kbn-optimizer/src/worker/entry_point_creator.ts, - /packages/kbn-ui-shared-deps/public_path_module_creator.js, ] `); }); diff --git a/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts b/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts index 6d296b9be089c0..8d890b31b639da 100644 --- a/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts +++ b/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts @@ -54,8 +54,19 @@ export class PopulateBundleCachePlugin { for (const module of compilation.modules) { if (isNormalModule(module)) { moduleCount += 1; - const path = getModulePath(module); - const parsedPath = parseFilePath(path); + let path = getModulePath(module); + let parsedPath = parseFilePath(path); + + if (parsedPath.dirs.includes('bazel-out')) { + const index = parsedPath.dirs.indexOf('bazel-out'); + path = Path.join( + workerConfig.repoRoot, + 'bazel-out', + ...parsedPath.dirs.slice(index + 1), + parsedPath.filename ?? '' + ); + parsedPath = parseFilePath(path); + } if (!parsedPath.dirs.includes('node_modules')) { referencedFiles.add(path); diff --git a/packages/kbn-securitysolution-hook-utils/BUILD.bazel b/packages/kbn-securitysolution-hook-utils/BUILD.bazel new file mode 100644 index 00000000000000..5bfe3d86867f6d --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/BUILD.bazel @@ -0,0 +1,87 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") + +PKG_BASE_NAME = "kbn-securitysolution-hook-utils" + +PKG_REQUIRE_NAME = "@kbn/securitysolution-hook-utils" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + "**/*.mock.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", + "README.md", +] + +SRC_DEPS = [ + "@npm//react", + "@npm//rxjs", + "@npm//tslib", +] + +TYPES_DEPS = [ + "@npm//@types/jest", + "@npm//@types/node", + "@npm//@types/react", +] + +DEPS = SRC_DEPS + TYPES_DEPS + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + ], +) + +ts_project( + name = "tsc", + srcs = SRCS, + args = ["--pretty"], + declaration = True, + declaration_map = True, + incremental = True, + out_dir = "target", + root_dir = "src", + source_map = True, + tsconfig = ":tsconfig", + deps = DEPS, +) + +js_library( + name = PKG_BASE_NAME, + package_name = PKG_REQUIRE_NAME, + srcs = NPM_MODULE_EXTRA_FILES, + visibility = ["//visibility:public"], + deps = DEPS + [":tsc"], +) + +pkg_npm( + name = "npm_module", + deps = [ + ":%s" % PKG_BASE_NAME, + ], +) + +filegroup( + name = "build", + srcs = [ + ":npm_module", + ], + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-securitysolution-hook-utils/README.md b/packages/kbn-securitysolution-hook-utils/README.md new file mode 100644 index 00000000000000..82d3d9d6866b21 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/README.md @@ -0,0 +1,3 @@ +# kbn-securitysolution-hook-utils + +This package contains shared utilities for React hooks. diff --git a/packages/kbn-securitysolution-hook-utils/jest.config.js b/packages/kbn-securitysolution-hook-utils/jest.config.js new file mode 100644 index 00000000000000..02fada76ea8323 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-securitysolution-hook-utils'], +}; diff --git a/packages/kbn-securitysolution-hook-utils/package.json b/packages/kbn-securitysolution-hook-utils/package.json new file mode 100644 index 00000000000000..6da17ab00f31c5 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/securitysolution-hook-utils", + "version": "1.0.0", + "description": "Security Solution utilities for React hooks", + "license": "SSPL-1.0 OR Elastic License 2.0", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "private": true +} diff --git a/packages/kbn-securitysolution-hook-utils/src/index.ts b/packages/kbn-securitysolution-hook-utils/src/index.ts new file mode 100644 index 00000000000000..47b0a6119f34f9 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/src/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './use_async'; +export * from './use_is_mounted'; +export * from './use_observable'; +export * from './with_optional_signal'; diff --git a/packages/kbn-securitysolution-hook-utils/src/types.ts b/packages/kbn-securitysolution-hook-utils/src/types.ts new file mode 100644 index 00000000000000..5d780059434b62 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/src/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Represents the state of an asynchronous task, along with an initiator + * function to kick off the work. + */ +export interface Task { + loading: boolean; + error: unknown | undefined; + result: Result | undefined; + start: (...args: Args) => void; +} diff --git a/packages/kbn-securitysolution-list-hooks/src/use_async/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-list-hooks/src/use_async/index.test.ts rename to packages/kbn-securitysolution-hook-utils/src/use_async/index.test.ts diff --git a/packages/kbn-securitysolution-list-hooks/src/use_async/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts similarity index 70% rename from packages/kbn-securitysolution-list-hooks/src/use_async/index.ts rename to packages/kbn-securitysolution-hook-utils/src/use_async/index.ts index 8a9048acbe3693..e284ba0f3c1e88 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_async/index.ts +++ b/packages/kbn-securitysolution-hook-utils/src/use_async/index.ts @@ -8,26 +8,26 @@ import { useCallback, useState } from 'react'; +import { Task } from '../types'; import { useIsMounted } from '../use_is_mounted'; -// TODO: This is probably better off in another package such as kbn-securitysolution-hook-utils - -export interface Async { - loading: boolean; - error: unknown | undefined; - result: Result | undefined; - start: (...args: Args) => void; -} - /** * - * @param fn Async function + * This hook wraps a promise-returning thunk (task) in order to conditionally + * initiate the work, and automatically provide state corresponding to the + * task's status. + * + * In order to function properly and not rerender unnecessarily, ensure that + * your task is a stable function reference. + * + * @param fn a function returning a promise. * - * @returns An {@link AsyncTask} containing the underlying task's state along with a start callback + * @returns An {@link Task} containing the task's current state along with a + * start callback */ export const useAsync = ( fn: (...args: Args) => Promise -): Async => { +): Task => { const isMounted = useIsMounted(); const [loading, setLoading] = useState(false); const [error, setError] = useState(); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_is_mounted/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-list-hooks/src/use_is_mounted/index.test.ts rename to packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.test.ts diff --git a/packages/kbn-securitysolution-list-hooks/src/use_is_mounted/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts similarity index 90% rename from packages/kbn-securitysolution-list-hooks/src/use_is_mounted/index.ts rename to packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts index 98c2a6cc3e4058..8b0db9c6a4c04c 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_is_mounted/index.ts +++ b/packages/kbn-securitysolution-hook-utils/src/use_is_mounted/index.ts @@ -10,8 +10,6 @@ import { useCallback, useEffect, useRef } from 'react'; type GetIsMounted = () => boolean; -// TODO: This is probably better off in another package such as kbn-securitysolution-hook-utils - /** * * @returns A {@link GetIsMounted} getter function returning whether the component is currently mounted diff --git a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts new file mode 100644 index 00000000000000..0c579be35ea0a2 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.test.ts @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { act, renderHook } from '@testing-library/react-hooks'; +import { Subject, throwError } from 'rxjs'; + +import { useObservable } from '.'; + +interface TestArgs { + n: number; + s: string; +} + +type TestReturn = Subject; + +describe('useObservable', () => { + let fn: jest.Mock; + let subject: TestReturn; + let args: TestArgs; + + beforeEach(() => { + args = { n: 1, s: 's' }; + subject = new Subject(); + fn = jest.fn().mockReturnValue(subject); + }); + + it('does not invoke fn if start was not called', () => { + renderHook(() => useObservable(fn)); + expect(fn).not.toHaveBeenCalled(); + }); + + it('invokes the function when start is called', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(fn).toHaveBeenCalled(); + }); + + it('invokes the function with start args', () => { + const { result } = renderHook(() => useObservable(fn)); + const expectedArgs = { ...args }; + + act(() => { + result.current.start(args); + }); + + expect(fn).toHaveBeenCalledWith(expectedArgs); + }); + + it('populates result with the next value of the fn', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + act(() => subject.next('value')); + + expect(result.current.result).toEqual('value'); + expect(result.current.error).toBeUndefined(); + }); + + it('populates error if observable throws an error', () => { + const error = new Error('whoops'); + const errorFn = () => throwError(error); + + const { result } = renderHook(() => useObservable(errorFn)); + + act(() => { + result.current.start(); + }); + + expect(result.current.result).toBeUndefined(); + expect(result.current.error).toEqual(error); + }); + + it('populates the loading state while no value has resolved', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => subject.next('a value')); + + expect(result.current.loading).toBe(false); + }); + + it('updates result with each resolved value', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + act(() => subject.next('a value')); + expect(result.current.result).toEqual('a value'); + + act(() => subject.next('a subsequent value')); + expect(result.current.result).toEqual('a subsequent value'); + }); + + it('does not update result with values if start has not been called', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => subject.next('a value')); + expect(result.current.result).toBeUndefined(); + + act(() => subject.next('a subsequent value')); + expect(result.current.result).toBeUndefined(); + }); + + it('unsubscribes on unmount', () => { + const { result, unmount } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + expect(subject.observers).toHaveLength(1); + + unmount(); + expect(subject.observers).toHaveLength(0); + }); + + it('multiple start calls reset state', () => { + const { result } = renderHook(() => useObservable(fn)); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + + act(() => subject.next('one value')); + + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('one value'); + + act(() => { + result.current.start(args); + }); + + expect(result.current.loading).toBe(true); + expect(result.current.result).toBe(undefined); + + act(() => subject.next('another value')); + + expect(result.current.loading).toBe(false); + expect(result.current.result).toBe('another value'); + }); +}); diff --git a/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts new file mode 100644 index 00000000000000..23c57ebbe41795 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/src/use_observable/index.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useCallback, useEffect, useRef, useState } from 'react'; +import { Observable, Subscription } from 'rxjs'; + +import { useIsMounted } from '../use_is_mounted'; +import { Task } from '../types'; + +/** + * + * @param fn function returning an observable + * + * @returns An {@link Async} containing the underlying task's state along with a start callback + */ +export const useObservable = ( + fn: (...args: Args) => Observable +): Task => { + const isMounted = useIsMounted(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + const [result, setResult] = useState(); + const subRef = useRef(); + + const start = useCallback( + (...args: Args) => { + if (subRef.current) { + subRef.current.unsubscribe(); + } + setLoading(true); + setResult(undefined); + setError(undefined); + + subRef.current = fn(...args).subscribe( + (r) => { + if (isMounted()) { + setResult(r); + setLoading(false); + } + }, + (e) => { + if (isMounted()) { + setError(e); + setLoading(false); + } + } + ); + }, + [fn, isMounted] + ); + + useEffect( + () => () => { + if (subRef.current) { + subRef.current.unsubscribe(); + } + }, + [] + ); + + return { + error, + loading, + result, + start, + }; +}; diff --git a/packages/kbn-securitysolution-list-hooks/src/with_optional_signal/index.test.ts b/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts similarity index 100% rename from packages/kbn-securitysolution-list-hooks/src/with_optional_signal/index.test.ts rename to packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.test.ts diff --git a/packages/kbn-securitysolution-list-hooks/src/with_optional_signal/index.ts b/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts similarity index 90% rename from packages/kbn-securitysolution-list-hooks/src/with_optional_signal/index.ts rename to packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts index 55d444e0e4d7a6..da6fd414abc575 100644 --- a/packages/kbn-securitysolution-list-hooks/src/with_optional_signal/index.ts +++ b/packages/kbn-securitysolution-hook-utils/src/with_optional_signal/index.ts @@ -12,8 +12,6 @@ interface SignalArgs { export type OptionalSignalArgs = Omit & Partial; -// TODO: This is probably better off in another package such as kbn-securitysolution-hook-utils - /** * * @param fn an async function receiving an AbortSignal argument diff --git a/packages/kbn-securitysolution-hook-utils/tsconfig.json b/packages/kbn-securitysolution-hook-utils/tsconfig.json new file mode 100644 index 00000000000000..352dc086fec30f --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "incremental": true, + "outDir": "target", + "rootDir": "src", + "sourceMap": true, + "sourceRoot": "../../../../packages/kbn-securitysolution-hook-utils/src", + "types": ["jest", "node"] + }, + "include": ["src/**/*"] +} diff --git a/packages/kbn-securitysolution-list-hooks/BUILD.bazel b/packages/kbn-securitysolution-list-hooks/BUILD.bazel index 1078d9bf3d329c..631e57958d5faf 100644 --- a/packages/kbn-securitysolution-list-hooks/BUILD.bazel +++ b/packages/kbn-securitysolution-list-hooks/BUILD.bazel @@ -28,6 +28,7 @@ NPM_MODULE_EXTRA_FILES = [ ] SRC_DEPS = [ + "//packages/kbn-securitysolution-hook-utils", "//packages/kbn-securitysolution-io-ts-list-types", "//packages/kbn-securitysolution-list-api", "//packages/kbn-securitysolution-list-constants", diff --git a/packages/kbn-securitysolution-list-hooks/src/index.ts b/packages/kbn-securitysolution-list-hooks/src/index.ts index 46d6a20deb0ac5..6e65c613de6177 100644 --- a/packages/kbn-securitysolution-list-hooks/src/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/index.ts @@ -7,7 +7,6 @@ */ export * from './transforms'; export * from './use_api'; -export * from './use_async'; export * from './use_create_list_index'; export * from './use_cursor'; export * from './use_delete_list'; @@ -16,9 +15,7 @@ export * from './use_exception_lists'; export * from './use_export_list'; export * from './use_find_lists'; export * from './use_import_list'; -export * from './use_is_mounted'; export * from './use_persist_exception_item'; export * from './use_persist_exception_list'; export * from './use_read_list_index'; export * from './use_read_list_privileges'; -export * from './with_optional_signal'; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts index 1682bcb5ebf5c2..b60e22fa02ba81 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_create_list_index/index.ts @@ -7,8 +7,7 @@ */ import { createListIndex } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const createListIndexWithOptionalSignal = withOptionalSignal(createListIndex); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts index 3be7056d5cf032..a89791f65972f6 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_delete_list/index.ts @@ -7,8 +7,7 @@ */ import { deleteList } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const deleteListWithOptionalSignal = withOptionalSignal(deleteList); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts index 9e312f7e3a112f..1d2da5e4c131eb 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_export_list/index.ts @@ -7,8 +7,7 @@ */ import { exportList } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const exportListWithOptionalSignal = withOptionalSignal(exportList); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts index 42d1c54e37ab42..b4251a5a7bcd21 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_find_lists/index.ts @@ -7,8 +7,7 @@ */ import { findLists } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const findListsWithOptionalSignal = withOptionalSignal(findLists); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts index f3c0cfb14130e8..f7274e9e0dd3e2 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_import_list/index.ts @@ -7,8 +7,7 @@ */ import { importList } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const importListWithOptionalSignal = withOptionalSignal(importList); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts index ef68b3ee6c3f91..18b2ef1ea04e0c 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_read_list_index/index.ts @@ -7,8 +7,7 @@ */ import { readListIndex } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const readListIndexWithOptionalSignal = withOptionalSignal(readListIndex); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts index f7c530196087ff..6159e2c288b2e2 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_read_list_privileges/index.ts @@ -7,8 +7,7 @@ */ import { readListPrivileges } from '@kbn/securitysolution-list-api'; -import { withOptionalSignal } from '../with_optional_signal'; -import { useAsync } from '../use_async'; +import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; const readListPrivilegesWithOptionalSignal = withOptionalSignal(readListPrivileges); diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json index 0e70f7c340a90a..f2e4c9b3418b1e 100644 --- a/packages/kbn-storybook/package.json +++ b/packages/kbn-storybook/package.json @@ -11,6 +11,6 @@ "scripts": { "build": "../../node_modules/.bin/tsc", "kbn:bootstrap": "yarn build", - "watch": "yarn build --watch" + "kbn:watch": "yarn build --watch" } } \ No newline at end of file diff --git a/packages/kbn-storybook/webpack.config.ts b/packages/kbn-storybook/webpack.config.ts index b1efa43fa194ba..972caf8d481fe9 100644 --- a/packages/kbn-storybook/webpack.config.ts +++ b/packages/kbn-storybook/webpack.config.ts @@ -71,11 +71,12 @@ export default function ({ config: storybookConfig }: { config: Configuration }) ], }, resolve: { - // Tell Webpack about the scss extension - extensions: ['.scss'], + extensions: ['.js', '.ts', '.tsx', '.json'], + mainFields: ['browser', 'main'], alias: { core_app_image_assets: resolve(REPO_ROOT, 'src/core/public/core_app/images'), }, + symlinks: false, }, stats, }; diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index 6a8f384208fd84..f9877447840da8 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -187,6 +187,19 @@ export const schema = Joi.object() sourceArgs: Joi.array(), serverArgs: Joi.array(), installDir: Joi.string(), + /** Options for how FTR should execute and interact with Kibana */ + runOptions: Joi.object() + .keys({ + /** + * Log message to wait for before initiating tests, defaults to waiting for Kibana status to be `available`. + * Note that this log message must not be filtered out by the current logging config, for example by the + * log level. If needed, you can adjust the logging level via `kbnTestServer.serverArgs`. + */ + wait: Joi.object() + .regex() + .default(/Kibana is now available/), + }) + .default(), }) .default(), diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js index f92d01d6454d50..3154d77488ba67 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js @@ -28,6 +28,7 @@ function extendNodeOptions(installDir) { export async function runKibanaServer({ procs, config, options }) { const { installDir } = options; + const runOptions = config.get('kbnTestServer.runOptions'); await procs.run('kibana', { cmd: getKibanaCmd(installDir), @@ -38,7 +39,7 @@ export async function runKibanaServer({ procs, config, options }) { ...extendNodeOptions(installDir), }, cwd: installDir || KIBANA_ROOT, - wait: /\[Kibana\]\[http\] http server running/, + wait: runOptions.wait, }); } diff --git a/packages/kbn-test/src/functional_tests/tasks.js b/packages/kbn-test/src/functional_tests/tasks.js index 122a5a23842d6f..f4dfdcb93fb2bf 100644 --- a/packages/kbn-test/src/functional_tests/tasks.js +++ b/packages/kbn-test/src/functional_tests/tasks.js @@ -97,8 +97,6 @@ export async function runTests(options) { try { es = await runElasticsearch({ config, options: opts }); await runKibanaServer({ procs, config, options: opts }); - // workaround until https://github.com/elastic/kibana/issues/89828 is addressed - await delay(5000); await runFtr({ configPath, options: opts }); } finally { try { @@ -164,7 +162,3 @@ async function silence(log, milliseconds) { ) .toPromise(); } - -async function delay(ms) { - await new Promise((resolve) => setTimeout(resolve, ms)); -} diff --git a/packages/kbn-tinymath/src/index.js b/packages/kbn-tinymath/src/index.js index 9f1bb7b8514634..6fde4c202e2a77 100644 --- a/packages/kbn-tinymath/src/index.js +++ b/packages/kbn-tinymath/src/index.js @@ -7,12 +7,11 @@ */ const { get } = require('lodash'); +const memoizeOne = require('memoize-one'); // eslint-disable-next-line import/no-unresolved const { parse: parseFn } = require('../grammar'); const { functions: includedFunctions } = require('./functions'); -module.exports = { parse, evaluate, interpret }; - function parse(input, options) { if (input == null) { throw new Error('Missing expression'); @@ -29,9 +28,11 @@ function parse(input, options) { } } +const memoizedParse = memoizeOne(parse); + function evaluate(expression, scope = {}, injectedFunctions = {}) { scope = scope || {}; - return interpret(parse(expression), scope, injectedFunctions); + return interpret(memoizedParse(expression), scope, injectedFunctions); } function interpret(node, scope, injectedFunctions) { @@ -79,3 +80,5 @@ function isOperable(args) { return typeof arg === 'number' && !isNaN(arg); }); } + +module.exports = { parse: memoizedParse, evaluate, interpret }; diff --git a/packages/kbn-ui-shared-deps/BUILD.bazel b/packages/kbn-ui-shared-deps/BUILD.bazel new file mode 100644 index 00000000000000..c04f88a42cce03 --- /dev/null +++ b/packages/kbn-ui-shared-deps/BUILD.bazel @@ -0,0 +1,145 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") +load("@npm//webpack-cli:index.bzl", webpack = "webpack_cli") + +PKG_BASE_NAME = "kbn-ui-shared-deps" +PKG_REQUIRE_NAME = "@kbn/ui-shared-deps" + +SOURCE_FILES = glob( + [ + "src/**/*", + ], + exclude = [ + "**/*.md", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "flot_charts/package.json", + "theme/package.json", + "package.json", + "README.md" +] + +SRC_DEPS = [ + "//packages/elastic-datemath", + "//packages/elastic-safer-lodash-set", + "//packages/kbn-analytics", + "//packages/kbn-babel-preset", + "//packages/kbn-i18n", + "//packages/kbn-monaco", + "//packages/kbn-std", + "//packages/kbn-utils", + "@npm//@elastic/charts", + "@npm//@elastic/eui", + "@npm//@elastic/numeral", + "@npm//abortcontroller-polyfill", + "@npm//angular", + "@npm//babel-loader", + "@npm//compression-webpack-plugin", + "@npm//core-js", + "@npm//css-minimizer-webpack-plugin", + "@npm//css-loader", + "@npm//fflate", + "@npm//jquery", + "@npm//loader-utils", + # TODO: we can remove this once EUI patches the dependencies + "@npm//mdast-util-to-hast", + "@npm//mini-css-extract-plugin", + "@npm//moment", + "@npm//moment-timezone", + "@npm//raw-loader", + "@npm//react", + "@npm//react-dom", + "@npm//react-intl", + "@npm//react-is", + "@npm//react-router", + "@npm//react-router-dom", + "@npm//regenerator-runtime", + "@npm//resize-observer-polyfill", + "@npm//rison-node", + "@npm//rxjs", + "@npm//styled-components", + "@npm//symbol-observable", + "@npm//terser-webpack-plugin", + "@npm//url-loader", + "@npm//val-loader", + "@npm//whatwg-fetch" +] + +TYPES_DEPS = [ + "@npm//@types/node", +] + +DEPS = SRC_DEPS + TYPES_DEPS + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + ], +) + +ts_project( + name = "tsc", + args = ['--pretty'], + srcs = SRCS, + deps = DEPS, + allow_js = True, + declaration = True, + declaration_map = True, + incremental = True, + out_dir = "target", + source_map = True, + root_dir = "src", + tsconfig = ":tsconfig", +) + +webpack( + name = "shared_built_assets", + data = DEPS + [ + "//:package.json", + ":srcs", + ":tsconfig", + ":webpack.config.js", + ], + output_dir = True, + args = [ + "--config", + "$(location webpack.config.js)", + "--output-path", + "$(@D)", + "--display=minimal" + ], +) + +js_library( + name = PKG_BASE_NAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = DEPS + [":tsc", ":shared_built_assets"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [ + ":%s" % PKG_BASE_NAME, + ] +) + +filegroup( + name = "build", + srcs = [ + ":npm_module", + ], + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-ui-shared-deps/flot_charts/package.json b/packages/kbn-ui-shared-deps/flot_charts/package.json new file mode 100644 index 00000000000000..03d7ac348fcb9a --- /dev/null +++ b/packages/kbn-ui-shared-deps/flot_charts/package.json @@ -0,0 +1,4 @@ +{ + "main": "../target/flot_charts/index.js", + "types": "../target/flot_charts/index.d.ts" +} \ No newline at end of file diff --git a/packages/kbn-ui-shared-deps/index.d.ts b/packages/kbn-ui-shared-deps/index.d.ts deleted file mode 100644 index 5d2986daeeb3bb..00000000000000 --- a/packages/kbn-ui-shared-deps/index.d.ts +++ /dev/null @@ -1,59 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -/** - * Absolute path to the distributable directory - */ -export const distDir: string; - -/** - * Filename of the main bundle file in the distributable directory - */ -export const jsFilename: string; - -/** - * Filename of files that must be loaded before the jsFilename - */ -export const jsDepFilenames: string[]; - -/** - * Filename of the unthemed css file in the distributable directory - */ -export const baseCssDistFilename: string; - -/** - * Filename of the dark-theme css file in the distributable directory - */ -export const darkCssDistFilename: string; - -/** - * Filename of the dark-theme css file in the distributable directory - */ -export const darkV8CssDistFilename: string; - -/** - * Filename of the light-theme css file in the distributable directory - */ -export const lightCssDistFilename: string; - -/** - * Filename of the light-theme css file in the distributable directory - */ -export const lightV8CssDistFilename: string; - -/** - * Externals mapping inteded to be used in a webpack config - */ -export const externals: { - [key: string]: string; -}; - -/** - * Webpack loader for configuring the public path lookup from `window.__kbnPublicPath__`. - */ -export const publicPathLoader: string; diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 162606585c43e5..5ec32ca059aa1b 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -3,9 +3,6 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "scripts": { - "build": "node scripts/build", - "kbn:bootstrap": "node scripts/build --dev", - "kbn:watch": "node scripts/build --dev --watch" - } + "main": "target/index.js", + "types": "target/index.d.ts" } \ No newline at end of file diff --git a/packages/kbn-ui-shared-deps/scripts/build.js b/packages/kbn-ui-shared-deps/scripts/build.js deleted file mode 100644 index 0993f785902464..00000000000000 --- a/packages/kbn-ui-shared-deps/scripts/build.js +++ /dev/null @@ -1,98 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -const Path = require('path'); - -const { run, createFailError } = require('@kbn/dev-utils'); -const webpack = require('webpack'); -const Stats = require('webpack/lib/Stats'); -const del = require('del'); - -const { getWebpackConfig } = require('../webpack.config'); - -const DIST_DIR = Path.resolve(__dirname, '../target'); - -run( - async ({ log, flags }) => { - log.info('cleaning previous build output'); - await del(DIST_DIR); - - const compiler = webpack( - getWebpackConfig({ - dev: flags.dev, - }) - ); - - /** @param {webpack.Stats} stats */ - const onCompilationComplete = async (stats) => { - const took = Math.round((stats.endTime - stats.startTime) / 1000); - - if (!stats.hasErrors() && !stats.hasWarnings()) { - log.success(`webpack completed in about ${took} seconds`); - return; - } - - throw createFailError( - `webpack failure in about ${took} seconds\n${stats.toString({ - colors: true, - ...Stats.presetToOptions('minimal'), - })}` - ); - }; - - if (flags.watch) { - compiler.hooks.done.tap('report on stats', (stats) => { - onCompilationComplete(stats).catch((error) => { - log.error(error.message); - }); - }); - - compiler.hooks.watchRun.tap('report on start', () => { - if (process.stdout.isTTY) { - process.stdout.cursorTo(0, 0); - process.stdout.clearScreenDown(); - } - - log.info('Running webpack compilation...'); - }); - - compiler.watch({}, (error) => { - if (error) { - log.error('Fatal webpack error'); - log.error(error); - process.exit(1); - } - }); - - return; - } - - log.info('running webpack'); - await onCompilationComplete( - await new Promise((resolve, reject) => { - compiler.run((error, stats) => { - if (error) { - reject(error); - } else { - resolve(stats); - } - }); - }) - ); - }, - { - description: 'build @kbn/ui-shared-deps', - flags: { - boolean: ['watch', 'dev'], - help: ` - --watch Run in watch mode - --dev Build development friendly version - `, - }, - } -); diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/src/entry.js similarity index 100% rename from packages/kbn-ui-shared-deps/entry.js rename to packages/kbn-ui-shared-deps/src/entry.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/API.md b/packages/kbn-ui-shared-deps/src/flot_charts/API.md similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/API.md rename to packages/kbn-ui-shared-deps/src/flot_charts/API.md diff --git a/packages/kbn-ui-shared-deps/flot_charts/index.js b/packages/kbn-ui-shared-deps/src/flot_charts/index.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/index.js rename to packages/kbn-ui-shared-deps/src/flot_charts/index.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_colorhelpers.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_colorhelpers.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_colorhelpers.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_colorhelpers.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_axislabels.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_axislabels.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_axislabels.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_axislabels.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_canvas.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_canvas.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_canvas.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_canvas.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_categories.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_categories.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_categories.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_categories.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_crosshair.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_crosshair.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_crosshair.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_crosshair.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_errorbars.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_errorbars.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_errorbars.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_errorbars.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_fillbetween.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_fillbetween.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_fillbetween.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_fillbetween.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_image.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_image.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_image.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_image.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_log.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_log.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_log.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_log.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_navigate.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_navigate.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_navigate.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_navigate.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_pie.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_pie.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_pie.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_pie.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_resize.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_resize.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_resize.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_resize.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_selection.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_selection.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_selection.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_selection.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_stack.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_stack.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_stack.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_stack.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_symbol.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_symbol.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_symbol.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_symbol.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_threshold.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_threshold.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_threshold.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_threshold.js diff --git a/packages/kbn-ui-shared-deps/flot_charts/jquery_flot_time.js b/packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_time.js similarity index 100% rename from packages/kbn-ui-shared-deps/flot_charts/jquery_flot_time.js rename to packages/kbn-ui-shared-deps/src/flot_charts/jquery_flot_time.js diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/src/index.js similarity index 78% rename from packages/kbn-ui-shared-deps/index.js rename to packages/kbn-ui-shared-deps/src/index.js index 877bf3df6c039d..c5853dc0918756 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/src/index.js @@ -8,14 +8,49 @@ const Path = require('path'); -exports.distDir = Path.resolve(__dirname, 'target'); +/** + * Absolute path to the distributable directory + */ +exports.distDir = Path.resolve(__dirname, '..', 'shared_built_assets'); + +/** + * Filename of files that must be loaded before the jsFilename + */ exports.jsDepFilenames = ['kbn-ui-shared-deps.@elastic.js']; + +/** + * Filename of the main bundle file in the distributable directory + */ exports.jsFilename = 'kbn-ui-shared-deps.js'; + +/** + * Filename of the unthemed css file in the distributable directory + */ exports.baseCssDistFilename = 'kbn-ui-shared-deps.css'; + +/** + * Filename of the light-theme css file in the distributable directory + */ exports.lightCssDistFilename = 'kbn-ui-shared-deps.v7.light.css'; + +/** + * Filename of the light-theme css file in the distributable directory + */ exports.lightV8CssDistFilename = 'kbn-ui-shared-deps.v8.light.css'; + +/** + * Filename of the dark-theme css file in the distributable directory + */ exports.darkCssDistFilename = 'kbn-ui-shared-deps.v7.dark.css'; + +/** + * Filename of the dark-theme css file in the distributable directory + */ exports.darkV8CssDistFilename = 'kbn-ui-shared-deps.v8.dark.css'; + +/** + * Externals mapping inteded to be used in a webpack config + */ exports.externals = { // stateful deps angular: '__kbnSharedDeps__.Angular', @@ -63,4 +98,8 @@ exports.externals = { '@elastic/safer-lodash-set': '__kbnSharedDeps__.SaferLodashSet', 'rison-node': '__kbnSharedDeps__.RisonNode', }; + +/** + * Webpack loader for configuring the public path lookup from `window.__kbnPublicPath__`. + */ exports.publicPathLoader = require.resolve('./public_path_loader'); diff --git a/packages/kbn-ui-shared-deps/polyfills.js b/packages/kbn-ui-shared-deps/src/polyfills.js similarity index 100% rename from packages/kbn-ui-shared-deps/polyfills.js rename to packages/kbn-ui-shared-deps/src/polyfills.js diff --git a/packages/kbn-ui-shared-deps/public_path_loader.js b/packages/kbn-ui-shared-deps/src/public_path_loader.js similarity index 100% rename from packages/kbn-ui-shared-deps/public_path_loader.js rename to packages/kbn-ui-shared-deps/src/public_path_loader.js diff --git a/packages/kbn-ui-shared-deps/public_path_module_creator.js b/packages/kbn-ui-shared-deps/src/public_path_module_creator.js similarity index 100% rename from packages/kbn-ui-shared-deps/public_path_module_creator.js rename to packages/kbn-ui-shared-deps/src/public_path_module_creator.js diff --git a/packages/kbn-ui-shared-deps/theme.ts b/packages/kbn-ui-shared-deps/src/theme.ts similarity index 100% rename from packages/kbn-ui-shared-deps/theme.ts rename to packages/kbn-ui-shared-deps/src/theme.ts diff --git a/packages/kbn-ui-shared-deps/theme/package.json b/packages/kbn-ui-shared-deps/theme/package.json new file mode 100644 index 00000000000000..2d41937701a294 --- /dev/null +++ b/packages/kbn-ui-shared-deps/theme/package.json @@ -0,0 +1,4 @@ +{ + "main": "../target/theme.js", + "types": "../target/theme.d.ts" +} \ No newline at end of file diff --git a/packages/kbn-ui-shared-deps/tsconfig.json b/packages/kbn-ui-shared-deps/tsconfig.json index 88699027f85de8..0fd49ede218308 100644 --- a/packages/kbn-ui-shared-deps/tsconfig.json +++ b/packages/kbn-ui-shared-deps/tsconfig.json @@ -1,10 +1,20 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "tsBuildInfoFile": "../../build/tsbuildinfo/packages/kbn-ui-shared-deps" + "allowJs": true, + "incremental": true, + "outDir": "./target", + "declaration": true, + "declarationMap": true, + "rootDir": "src", + "sourceMap": true, + "sourceRoot": "../../../../packages/kbn-ui-shared-deps/src", + "types": [ + "node", + "resize-observer-polyfill" + ] }, "include": [ - "index.d.ts", - "theme.ts" + "src/**/*", ] } diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js index 76e6843bea2f82..438b1e0b2e77bd 100644 --- a/packages/kbn-ui-shared-deps/webpack.config.js +++ b/packages/kbn-ui-shared-deps/webpack.config.js @@ -7,6 +7,7 @@ */ const Path = require('path'); +const Os = require('os'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); @@ -14,24 +15,23 @@ const TerserPlugin = require('terser-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); const { REPO_ROOT } = require('@kbn/utils'); -const webpack = require('webpack'); const { RawSource } = require('webpack-sources'); -const UiSharedDeps = require('./index'); +const UiSharedDeps = require('./src/index'); const MOMENT_SRC = require.resolve('moment/min/moment-with-locales.js'); -exports.getWebpackConfig = ({ dev = false } = {}) => ({ - mode: dev ? 'development' : 'production', +module.exports = { + mode: 'production', entry: { - 'kbn-ui-shared-deps': './entry.js', + 'kbn-ui-shared-deps': './src/entry.js', 'kbn-ui-shared-deps.v7.dark': ['@elastic/eui/dist/eui_theme_dark.css'], 'kbn-ui-shared-deps.v7.light': ['@elastic/eui/dist/eui_theme_light.css'], 'kbn-ui-shared-deps.v8.dark': ['@elastic/eui/dist/eui_theme_amsterdam_dark.css'], 'kbn-ui-shared-deps.v8.light': ['@elastic/eui/dist/eui_theme_amsterdam_light.css'], }, context: __dirname, - devtool: dev ? '#cheap-source-map' : false, + devtool: 'cheap-source-map', output: { path: UiSharedDeps.distDir, filename: '[name].js', @@ -39,13 +39,14 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ devtoolModuleFilenameTemplate: (info) => `kbn-ui-shared-deps/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`, library: '__kbnSharedDeps__', + futureEmitAssets: true, }, module: { noParse: [MOMENT_SRC], rules: [ { - include: [require.resolve('./entry.js')], + include: [require.resolve('./src/entry.js')], use: [ { loader: UiSharedDeps.publicPathLoader, @@ -60,7 +61,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ use: [MiniCssExtractPlugin.loader, 'css-loader'], }, { - include: [require.resolve('./theme.ts')], + include: [require.resolve('./src/theme.ts')], use: [ { loader: 'babel-loader', @@ -71,7 +72,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ ], }, { - test: !dev ? /[\\\/]@elastic[\\\/]eui[\\\/].*\.js$/ : () => false, + test: /[\\\/]@elastic[\\\/]eui[\\\/].*\.js$/, use: [ { loader: 'babel-loader', @@ -110,6 +111,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ optimization: { minimizer: [ new CssMinimizerPlugin({ + parallel: Math.min(Os.cpus().length, 2), minimizerOptions: { preset: [ 'default', @@ -123,7 +125,7 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ cache: false, sourceMap: false, extractComments: false, - parallel: false, + parallel: Math.min(Os.cpus().length, 2), terserOptions: { compress: true, mangle: true, @@ -154,54 +156,44 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ new MiniCssExtractPlugin({ filename: '[name].css', }), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': dev ? '"development"' : '"production"', + new CompressionPlugin({ + algorithm: 'brotliCompress', + filename: '[path].br', + test: /\.(js|css)$/, + cache: false, }), - ...(dev - ? [] - : [ - new CompressionPlugin({ - algorithm: 'brotliCompress', - filename: '[path].br', - test: /\.(js|css)$/, - cache: false, - }), - new CompressionPlugin({ - algorithm: 'gzip', - filename: '[path].gz', - test: /\.(js|css)$/, - cache: false, - }), - new (class MetricsPlugin { - apply(compiler) { - compiler.hooks.emit.tap('MetricsPlugin', (compilation) => { - const metrics = [ - { - group: 'page load bundle size', - id: 'kbnUiSharedDeps-js', - value: compilation.assets['kbn-ui-shared-deps.js'].size(), - }, - { - group: 'page load bundle size', - id: 'kbnUiSharedDeps-css', - value: - compilation.assets['kbn-ui-shared-deps.css'].size() + - compilation.assets['kbn-ui-shared-deps.v7.light.css'].size(), - }, - { - group: 'page load bundle size', - id: 'kbnUiSharedDeps-elastic', - value: compilation.assets['kbn-ui-shared-deps.@elastic.js'].size(), - }, - ]; + new CompressionPlugin({ + algorithm: 'gzip', + filename: '[path].gz', + test: /\.(js|css)$/, + cache: false, + }), + new (class MetricsPlugin { + apply(compiler) { + compiler.hooks.emit.tap('MetricsPlugin', (compilation) => { + const metrics = [ + { + group: 'page load bundle size', + id: 'kbnUiSharedDeps-js', + value: compilation.assets['kbn-ui-shared-deps.js'].size(), + }, + { + group: 'page load bundle size', + id: 'kbnUiSharedDeps-css', + value: + compilation.assets['kbn-ui-shared-deps.css'].size() + + compilation.assets['kbn-ui-shared-deps.v7.light.css'].size(), + }, + { + group: 'page load bundle size', + id: 'kbnUiSharedDeps-elastic', + value: compilation.assets['kbn-ui-shared-deps.@elastic.js'].size(), + }, + ]; - compilation.emitAsset( - 'metrics.json', - new RawSource(JSON.stringify(metrics, null, 2)) - ); - }); - } - })(), - ]), + compilation.emitAsset('metrics.json', new RawSource(JSON.stringify(metrics, null, 2))); + }); + } + })(), ], -}); +}; diff --git a/renovate.json5 b/renovate.json5 index f533eac4796508..2a3b9d740ee93b 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -39,7 +39,7 @@ packageNames: ['@elastic/charts'], reviewers: ['markov00', 'nickofthyme'], matchBaseBranches: ['master'], - labels: ['release_note:skip', 'v8.0.0', 'v7.14.0'], + labels: ['release_note:skip', 'v8.0.0', 'v7.14.0', 'auto-backport'], enabled: true, }, { diff --git a/rfcs/text/0011_global_search.md b/rfcs/text/0011_global_search.md index 3b2120283d06a0..28ebf1a64a1125 100644 --- a/rfcs/text/0011_global_search.md +++ b/rfcs/text/0011_global_search.md @@ -7,8 +7,6 @@ A new Kibana plugin exposing an API on both public and server side, to allow consumers to search for various objects and register result providers. -Note: whether this will be an oss or xpack plugin still depends on https://github.com/elastic/dev/issues/1404. - # Basic example - registering a result provider: @@ -43,8 +41,7 @@ Kibana should do its best to assist users searching for and navigating to the va We should expose an API to make it possible for plugins to search for the various objects present on a Kibana instance. -The first consumer of this API will be the global search bar [#57576](https://github.com/elastic/kibana/issues/57576). This API -should still be generic to answer similar needs from any other consumer, either client or server side. +The first consumer of this API will be the global search bar [#57576](https://github.com/elastic/kibana/issues/57576). This API should still be generic to answer similar needs from any other consumer, either client or server side. # Detailed design @@ -84,7 +81,7 @@ interface GlobalSearchProviderFindOptions { aborted$: Observable; /** * The total maximum number of results (including all batches / emissions) that should be returned by the provider for a given `find` request. - * Any result emitted exceeding this quota will be ignored by the service and not emitted to the consumer. + * Any result emitted exceeding this quota will be ignored by the service and not emitted to the consumer. */ maxResults: number; } @@ -462,8 +459,8 @@ search( Notes: -- The example implementation is not streaming results from the server, meaning that all results from server-side - registered providers will all be fetched and emitted in a single batch. Ideally, we would leverage the `bfetch` plugin +- The example implementation is not streaming results from the server, meaning that all results from server-side + registered providers will all be fetched and emitted in a single batch. Ideally, we would leverage the `bfetch` plugin to stream the results to the client instead. ### results sorting diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 06277d9351922c..95091a761639b6 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -22,6 +22,7 @@ export class DocLinksService { const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/'; const ELASTICSEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; const KIBANA_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/`; + const FLEET_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/fleet/${DOC_LINK_VERSION}/`; const PLUGIN_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/plugins/${DOC_LINK_VERSION}/`; return deepFreeze({ @@ -400,6 +401,19 @@ export class DocLinksService { urlDecode: `${ELASTICSEARCH_DOCS}urldecode-processor.html`, userAgent: `${ELASTICSEARCH_DOCS}user-agent-processor.html`, }, + fleet: { + guide: `${FLEET_DOCS}index.html`, + fleetServer: `${FLEET_DOCS}fleet-server.html`, + fleetServerAddFleetServer: `${FLEET_DOCS}fleet-server.html#add-fleet-server`, + settings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`, + settingsFleetServerHostSettings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`, + troubleshooting: `${FLEET_DOCS}fleet-troubleshooting.html`, + elasticAgent: `${FLEET_DOCS}elastic-agent-installation-configuration.html`, + datastreams: `${FLEET_DOCS}data-streams.html`, + datastreamsNamingScheme: `${FLEET_DOCS}data-streams.html#data-streams-naming-scheme`, + upgradeElasticAgent: `${FLEET_DOCS}upgrade-elastic-agent.html`, + upgradeElasticAgent712lower: `${FLEET_DOCS}upgrade-elastic-agent.html#upgrade-7.12-lower`, + }, }, }); } @@ -587,5 +601,18 @@ export interface DocLinksStart { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; } diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index d3426b50f76143..6cc2b3f321fb7c 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -664,6 +664,19 @@ export interface DocLinksStart { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; } diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff new file mode 100644 index 00000000000000..2f5cb41bea12e8 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff2 new file mode 100644 index 00000000000000..53c0aa239d2b6d Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Black.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff new file mode 100644 index 00000000000000..a168e58200e02d Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff2 new file mode 100644 index 00000000000000..63ec88686361fd Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-BlackItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff new file mode 100644 index 00000000000000..2ec7ac3d21374e Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff2 new file mode 100644 index 00000000000000..6989c99229e7f7 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Bold.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff new file mode 100644 index 00000000000000..aa35b797455ade Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff2 new file mode 100644 index 00000000000000..18b4c1ce5ec005 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-BoldItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff new file mode 100644 index 00000000000000..d79d3d242aca8f Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff2 new file mode 100644 index 00000000000000..3e74973f27ea80 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBold.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff new file mode 100644 index 00000000000000..06aad19b0e1196 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff2 new file mode 100644 index 00000000000000..77391ea7f2cbc9 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraBoldItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff new file mode 100644 index 00000000000000..fee5fca026ef23 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff2 new file mode 100644 index 00000000000000..607250b9ac617c Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLight.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff new file mode 100644 index 00000000000000..94e6582b5a11e7 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff2 new file mode 100644 index 00000000000000..858d38a50f9ee6 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ExtraLightItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff new file mode 100644 index 00000000000000..4b765bd59291b3 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff2 new file mode 100644 index 00000000000000..bd5f255a9894a0 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Italic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff new file mode 100644 index 00000000000000..7590ff890939e1 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff2 new file mode 100644 index 00000000000000..551410ac3ef6fa Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Light.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff new file mode 100644 index 00000000000000..8f2a4ca464d907 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff2 new file mode 100644 index 00000000000000..976d52564f2e4d Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-LightItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff new file mode 100644 index 00000000000000..7d55f34ccabdea Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff2 new file mode 100644 index 00000000000000..a916b47fc84c44 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Medium.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff new file mode 100644 index 00000000000000..422ab0576ad521 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff2 new file mode 100644 index 00000000000000..f623924aeabe3d Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-MediumItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff new file mode 100644 index 00000000000000..7ff51b7d8fb17e Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff2 new file mode 100644 index 00000000000000..554aed6612722d Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Regular.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff new file mode 100644 index 00000000000000..76e507a515bd8c Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff2 new file mode 100644 index 00000000000000..9307998993f7e1 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBold.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff new file mode 100644 index 00000000000000..382181212d4266 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff2 new file mode 100644 index 00000000000000..f19f5505ec1076 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-SemiBoldItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff b/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff new file mode 100644 index 00000000000000..6074d22b98b302 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff2 new file mode 100644 index 00000000000000..07d4fd6f2a694a Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-Thin.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff b/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff new file mode 100644 index 00000000000000..e612ae45ec215c Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff2 new file mode 100644 index 00000000000000..a824b2c9871696 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-ThinItalic.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-italic.var.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-italic.var.woff2 new file mode 100644 index 00000000000000..03875311af6d9a Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-italic.var.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter-roman.var.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter-roman.var.woff2 new file mode 100644 index 00000000000000..a6efdc48675a7f Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter-roman.var.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/Inter.var.woff2 b/src/core/server/core_app/assets/fonts/inter/Inter.var.woff2 new file mode 100644 index 00000000000000..b40083cbbe3b27 Binary files /dev/null and b/src/core/server/core_app/assets/fonts/inter/Inter.var.woff2 differ diff --git a/src/core/server/core_app/assets/fonts/inter/LICENSE.txt b/src/core/server/core_app/assets/fonts/inter/LICENSE.txt new file mode 100644 index 00000000000000..ff80f8c615684e --- /dev/null +++ b/src/core/server/core_app/assets/fonts/inter/LICENSE.txt @@ -0,0 +1,94 @@ +Copyright (c) 2016-2020 The Inter Project Authors. +"Inter" is trademark of Rasmus Andersson. +https://github.com/rsms/inter + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/core/server/core_app/assets/fonts/readme.md b/src/core/server/core_app/assets/fonts/readme.md index 4042fd98a7a0e0..be217c653a7762 100644 --- a/src/core/server/core_app/assets/fonts/readme.md +++ b/src/core/server/core_app/assets/fonts/readme.md @@ -1,7 +1,8 @@ ## Font usage -Kibana packages two fonts: +Kibana packages three fonts: +* [Inter](https://rsms.me/inter/) fonts were pulled from their site and are at v3.18 * [Inter UI](https://rsms.me/inter/) fonts were pulled from their site and are at v3.2 * [Roboto Mono](https://fonts.google.com/specimen/Roboto+Mono) was pulled from the Google Fonts website on January 22, 2019. diff --git a/src/core/server/core_usage_data/core_usage_data_service.ts b/src/core/server/core_usage_data/core_usage_data_service.ts index dc24f889cd8dd4..afe1b45175f864 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.ts @@ -126,14 +126,12 @@ export class CoreUsageDataService implements CoreService; } -export const Fonts: FunctionComponent = ({ url }) => { - const interUi: FontFace = { +/** + * `Inter` is the latest version of `Inter UI` and used specifically in v8 of Kibana from EUI Amsterdam + */ +const getInter = (url: string): FontFace => { + return { + family: 'Inter', + variants: [ + { + style: 'normal', + weight: 100, + sources: [`${url}/fonts/inter/Inter-Thin.woff2`, `${url}/fonts/inter/Inter-Thin.woff`], + }, + { + style: 'italic', + weight: 100, + sources: [ + `${url}/fonts/inter/Inter-ThinItalic.woff2`, + `${url}/fonts/inter/Inter-ThinItalic.woff`, + ], + }, + { + style: 'normal', + weight: 200, + sources: [ + `${url}/fonts/inter/Inter-ExtraLight.woff2`, + `${url}/fonts/inter/Inter-ExtraLight.woff`, + ], + }, + { + style: 'italic', + weight: 200, + sources: [ + `${url}/fonts/inter/Inter-ExtraLightItalic.woff2`, + `${url}/fonts/inter/Inter-ExtraLightItalic.woff`, + ], + }, + { + style: 'normal', + weight: 300, + sources: [`${url}/fonts/inter/Inter-Light.woff2`, `${url}/fonts/inter/Inter-Light.woff`], + }, + { + style: 'italic', + weight: 300, + sources: [ + `${url}/fonts/inter/Inter-LightItalic.woff2`, + `${url}/fonts/inter/Inter-LightItalic.woff`, + ], + }, + { + style: 'normal', + weight: 400, + sources: [ + `${url}/fonts/inter/Inter-Regular.woff2`, + `${url}/fonts/inter/Inter-Regular.woff`, + ], + }, + { + style: 'italic', + weight: 400, + sources: [`${url}/fonts/inter/Inter-Italic.woff2`, `${url}/fonts/inter/Inter-Italic.woff`], + }, + { + style: 'normal', + weight: 500, + sources: [`${url}/fonts/inter/Inter-Medium.woff2`, `${url}/fonts/inter/Inter-Medium.woff`], + }, + { + style: 'italic', + weight: 500, + sources: [ + `${url}/fonts/inter/Inter-MediumItalic.woff2`, + `${url}/fonts/inter/Inter-MediumItalic.woff`, + ], + }, + { + style: 'normal', + weight: 600, + sources: [ + `${url}/fonts/inter/Inter-SemiBold.woff2`, + `${url}/fonts/inter/Inter-SemiBold.woff`, + ], + }, + { + style: 'italic', + weight: 600, + sources: [ + `${url}/fonts/inter/Inter-SemiBoldItalic.woff2`, + `${url}/fonts/inter/Inter-SemiBoldItalic.woff`, + ], + }, + { + style: 'normal', + weight: 700, + sources: [`${url}/fonts/inter/Inter-Bold.woff2`, `${url}/fonts/inter/Inter-Bold.woff`], + }, + { + style: 'italic', + weight: 700, + sources: [ + `${url}/fonts/inter/Inter-BoldItalic.woff2`, + `${url}/fonts/inter/Inter-BoldItalic.woff`, + ], + }, + { + style: 'normal', + weight: 800, + sources: [ + `${url}/fonts/inter/Inter-ExtraBold.woff2`, + `${url}/fonts/inter/Inter-ExtraBold.woff`, + ], + }, + { + style: 'italic', + weight: 800, + sources: [ + `${url}/fonts/inter/Inter-ExtraBoldItalic.woff2`, + `${url}/fonts/inter/Inter-ExtraBoldItalic.woff`, + ], + }, + { + style: 'normal', + weight: 900, + sources: [`${url}/fonts/inter/Inter-Black.woff2`, `${url}/fonts/inter/Inter-Black.woff`], + }, + { + style: 'italic', + weight: 900, + sources: [ + `${url}/fonts/inter/Inter-BlackItalic.woff2`, + `${url}/fonts/inter/Inter-BlackItalic.woff`, + ], + }, + ], + }; +}; + +const getInterUi = (url: string): FontFace => { + return { family: 'Inter UI', variants: [ { @@ -177,7 +315,10 @@ export const Fonts: FunctionComponent = ({ url }) => { }, ], }; - const roboto: FontFace = { +}; + +const getRoboto = (url: string): FontFace => { + return { family: 'Roboto Mono', variants: [ { @@ -229,12 +370,20 @@ export const Fonts: FunctionComponent = ({ url }) => { }, ], }; +}; + +export const Fonts: FunctionComponent = ({ url, themeVersion }) => { + /** + * If `themeVersion` is not provided, we want to fallback to the newest font family `Inter` + */ + const sansFont = themeVersion === 'v7' ? getInterUi(url) : getInter(url); + const codeFont = getRoboto(url); return (