diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cfe7d560c1d89..1a6851a5a6424 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -86,7 +86,8 @@ x-pack/test/cloud_integration/plugins/saml_provider @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_links @elastic/kibana-core x-pack/plugins/cloud @elastic/kibana-core x-pack/plugins/cloud_security_posture @elastic/kibana-cloud-security-posture -packages/shared-ux/code_editor @elastic/appex-sharedux +packages/shared-ux/code_editor/impl @elastic/appex-sharedux +packages/shared-ux/code_editor/mocks @elastic/appex-sharedux packages/kbn-code-owners @elastic/appex-qa packages/kbn-coloring @elastic/kibana-visualizations packages/kbn-config @elastic/kibana-core @@ -487,6 +488,7 @@ x-pack/plugins/kubernetes_security @elastic/kibana-cloud-security-posture packages/kbn-language-documentation-popover @elastic/kibana-visualizations packages/kbn-lens-embeddable-utils @elastic/obs-ux-infra_services-team @elastic/kibana-visualizations packages/kbn-lens-formula-docs @elastic/kibana-visualizations +x-pack/examples/lens_embeddable_inline_editing_example @elastic/kibana-visualizations x-pack/plugins/lens @elastic/kibana-visualizations x-pack/plugins/license_api_guard @elastic/platform-deployment-management x-pack/plugins/license_management @elastic/platform-deployment-management diff --git a/examples/expressions_explorer/public/editor/expression_editor.tsx b/examples/expressions_explorer/public/editor/expression_editor.tsx index c940a21fada27..998a9e486ba19 100644 --- a/examples/expressions_explorer/public/editor/expression_editor.tsx +++ b/examples/expressions_explorer/public/editor/expression_editor.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { CodeEditor } from '@kbn/kibana-react-plugin/public'; +import { CodeEditor } from '@kbn/code-editor'; interface Props { value: string; diff --git a/examples/expressions_explorer/tsconfig.json b/examples/expressions_explorer/tsconfig.json index 717a797173597..b75817c68be7c 100644 --- a/examples/expressions_explorer/tsconfig.json +++ b/examples/expressions_explorer/tsconfig.json @@ -22,5 +22,6 @@ "@kbn/i18n", "@kbn/i18n-react", "@kbn/core-ui-settings-browser", + "@kbn/code-editor", ] } diff --git a/package.json b/package.json index 7c319089540f8..e62fbc7814b0c 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,8 @@ "@kbn/cloud-links-plugin": "link:x-pack/plugins/cloud_integrations/cloud_links", "@kbn/cloud-plugin": "link:x-pack/plugins/cloud", "@kbn/cloud-security-posture-plugin": "link:x-pack/plugins/cloud_security_posture", - "@kbn/code-editor": "link:packages/shared-ux/code_editor", + "@kbn/code-editor": "link:packages/shared-ux/code_editor/impl", + "@kbn/code-editor-mock": "link:packages/shared-ux/code_editor/mocks", "@kbn/coloring": "link:packages/kbn-coloring", "@kbn/config": "link:packages/kbn-config", "@kbn/config-mocks": "link:packages/kbn-config-mocks", @@ -509,6 +510,7 @@ "@kbn/language-documentation-popover": "link:packages/kbn-language-documentation-popover", "@kbn/lens-embeddable-utils": "link:packages/kbn-lens-embeddable-utils", "@kbn/lens-formula-docs": "link:packages/kbn-lens-formula-docs", + "@kbn/lens-inline-editing-example-plugin": "link:x-pack/examples/lens_embeddable_inline_editing_example", "@kbn/lens-plugin": "link:x-pack/plugins/lens", "@kbn/license-api-guard-plugin": "link:x-pack/plugins/license_api_guard", "@kbn/license-management-plugin": "link:x-pack/plugins/license_management", @@ -1307,6 +1309,7 @@ "@octokit/rest": "^16.35.0", "@openpgp/web-stream-tools": "^0.0.10", "@parcel/watcher": "^2.1.0", + "@redocly/cli": "^1.6.0", "@storybook/addon-a11y": "^6.5.16", "@storybook/addon-actions": "^6.5.16", "@storybook/addon-controls": "^6.5.16", diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts index a207162e060cb..d886ee3a5d6ac 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts @@ -133,33 +133,36 @@ describe('findActiveNodes', () => { title: 'Root', path: 'root', }, + // Group 1 '[0][0]': { id: 'group1', title: 'Group 1', - deepLink: getDeepLink('group1', 'group1'), path: 'root.group1', }, '[0][0][0]': { - id: 'group1A', - title: 'Group 1A', - path: 'root.group1.group1A', - }, - '[0][0][0][0]': { id: 'item1', title: 'Item 1', - deepLink: getDeepLink('item1', 'item1'), - path: 'root.group1.group1A.item1', + deepLink: getDeepLink('item1', 'item1'), // First match + path: 'root.group1.item1', }, + // Group 2 '[0][1]': { id: 'group2', title: 'Group 2', + deepLink: getDeepLink('group2', 'group2'), path: 'root.group2', }, '[0][1][0]': { + id: 'group2A', + title: 'Group 2A', + path: 'root.group2.group2A', + }, + '[0][1][0][0]': { id: 'item2', title: 'Item 2', - deepLink: getDeepLink('item1', 'item1'), // Same link as above, should match both - path: 'root.group2.item2', + // Second match --> should come first as it is the longest match of the 2 + deepLink: getDeepLink('item1', 'item1'), + path: 'root.group2.group2A.item2', }, }; @@ -172,21 +175,21 @@ describe('findActiveNodes', () => { path: 'root', }, { - id: 'group1', - title: 'Group 1', - deepLink: getDeepLink('group1', 'group1'), - path: 'root.group1', + id: 'group2', + title: 'Group 2', + deepLink: getDeepLink('group2', 'group2'), + path: 'root.group2', }, { - id: 'group1A', - title: 'Group 1A', - path: 'root.group1.group1A', + id: 'group2A', + title: 'Group 2A', + path: 'root.group2.group2A', }, { - id: 'item1', - title: 'Item 1', + id: 'item2', + title: 'Item 2', deepLink: getDeepLink('item1', 'item1'), - path: 'root.group1.group1A.item1', + path: 'root.group2.group2A.item2', }, ], [ @@ -196,15 +199,15 @@ describe('findActiveNodes', () => { path: 'root', }, { - id: 'group2', - title: 'Group 2', - path: 'root.group2', + id: 'group1', + title: 'Group 1', + path: 'root.group1', }, { - id: 'item2', - title: 'Item 2', + id: 'item1', + title: 'Item 1', deepLink: getDeepLink('item1', 'item1'), - path: 'root.group2.item2', + path: 'root.group1.item1', }, ], ]); diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts index 63f7f8e612c2e..c025872d736b0 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts @@ -137,6 +137,9 @@ export const findActiveNodes = ( matches[length] = []; } matches[length].push(key); + // If there are multiple node matches of the same URL path length, we want to order them by + // tree depth, so that the longest match (deepest node) comes first. + matches[length].sort((a, b) => b.length - a.length); } } }); diff --git a/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts b/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts new file mode 100644 index 0000000000000..a548e55f575a4 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts @@ -0,0 +1,67 @@ +/* + * 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 { ApmFields, Instance } from '@kbn/apm-synthtrace-client'; +import { service } from '@kbn/apm-synthtrace-client/src/lib/apm/service'; +import { Scenario } from '../cli/scenario'; +import { RunOptions } from '../cli/utils/parse_run_cli_flags'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); +const MAX_DEPENDENCIES = 10000; +const MAX_DEPENDENCIES_PER_SERVICE = 500; +const MAX_SERVICES = 20; + +const scenario: Scenario = async (runOptions: RunOptions) => { + return { + generate: ({ range, clients: { apmEsClient } }) => { + const javaInstances = Array.from({ length: MAX_SERVICES }).map((_, index) => + service(`opbeans-java-${index}`, ENVIRONMENT, 'java').instance(`java-instance-${index}`) + ); + + const instanceDependencies = (instance: Instance, startIndex: number) => { + const rate = range.ratePerMinute(60); + + return rate.generator((timestamp, index) => { + const currentIndex = index % MAX_DEPENDENCIES_PER_SERVICE; + const destination = (startIndex + currentIndex) % MAX_DEPENDENCIES; + + const span = instance + .transaction({ transactionName: 'GET /java' }) + .timestamp(timestamp) + .duration(400) + .success() + .children( + instance + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) + .destination(`elasticsearch/${destination}`) + .timestamp(timestamp) + .duration(200) + .success() + ); + + return span; + }); + }; + + return withClient( + apmEsClient, + javaInstances.map((instance, index) => + instanceDependencies(instance, (index * MAX_DEPENDENCIES_PER_SERVICE) % MAX_DEPENDENCIES) + ) + ); + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts index 199379e74eb9d..2f90e03099350 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts @@ -113,15 +113,13 @@ describe('lens_attributes_builder', () => { formulaAPI, }); const builder = new LensAttributesBuilder({ visualization: metriChart }); + const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer: { columnOrder: ['metric_formula_accessor'], @@ -156,14 +154,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: metriChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer: { columnOrder: ['metric_formula_accessor'], @@ -215,14 +210,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0'], @@ -272,14 +264,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0'], @@ -340,14 +329,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0', 'formula_accessor_0_1'], diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts index 5e0e5dc1de2a7..aa13813e37b82 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts @@ -79,9 +79,6 @@ test('generates gauge chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts index cfcabb131b451..91786a0b91e23 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts @@ -81,9 +81,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts index cf82d3a2f5f4d..86078332ebb42 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts @@ -79,9 +79,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts index 22ee18f3e5f3e..120b3069552d8 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts index 0093b03e33bc3..4fd97797b69dd 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts index 909f3e737ac99..dbe67d15416c4 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts index 08885ba57ba83..fe94e8f789d43 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts index d1646b4c0ec7d..42dc00dc2ba26 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts @@ -87,9 +87,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts index 7709c6969b29f..b4b7c7ddc4842 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts @@ -199,9 +199,6 @@ describe('buildDatasourceStates', () => { ); expect(results).toMatchInlineSnapshot(` Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/utils.ts b/packages/kbn-lens-embeddable-utils/config_builder/utils.ts index 21c48ca76a52b..78434f8dbb10f 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/utils.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/utils.ts @@ -191,10 +191,7 @@ export const buildDatasourceStates = async ( getValueColumns: (config: any, i: number) => TextBasedLayerColumn[], dataViewsAPI: DataViewsPublicPluginStart ) => { - const layers: LensAttributes['state']['datasourceStates'] = { - textBased: { layers: {} }, - formBased: { layers: {} }, - }; + let layers: Partial = {}; const mainDataset = config.dataset; const configLayers = 'layers' in config ? config.layers : [config]; @@ -226,7 +223,14 @@ export const buildDatasourceStates = async ( getValueColumns ); if (layerConfig) { - layers[type]!.layers[layerId] = layerConfig; + layers = { + ...layers, + [type]: { + layers: { + [layerId]: layerConfig, + }, + }, + }; } } } diff --git a/packages/kbn-management/settings/components/field_input/code_editor.tsx b/packages/kbn-management/settings/components/field_input/code_editor.tsx index 3f46778917fdd..ac1ea672d8a15 100644 --- a/packages/kbn-management/settings/components/field_input/code_editor.tsx +++ b/packages/kbn-management/settings/components/field_input/code_editor.tsx @@ -15,11 +15,12 @@ import React, { useCallback } from 'react'; import { monaco, XJsonLang } from '@kbn/monaco'; + import { CodeEditor as KibanaReactCodeEditor, - MarkdownLang, type CodeEditorProps as KibanaReactCodeEditorProps, -} from '@kbn/kibana-react-plugin/public'; + MarkdownLang, +} from '@kbn/code-editor'; type Props = Pick; type Options = KibanaReactCodeEditorProps['options']; diff --git a/packages/kbn-management/settings/components/field_input/tsconfig.json b/packages/kbn-management/settings/components/field_input/tsconfig.json index bb4c6b4aa57d0..d971549abb2d4 100644 --- a/packages/kbn-management/settings/components/field_input/tsconfig.json +++ b/packages/kbn-management/settings/components/field_input/tsconfig.json @@ -19,7 +19,6 @@ "@kbn/management-settings-types", "@kbn/management-settings-field-definition", "@kbn/monaco", - "@kbn/kibana-react-plugin", "@kbn/management-settings-utilities", "@kbn/i18n-react", "@kbn/i18n", @@ -30,5 +29,6 @@ "@kbn/core-i18n-browser", "@kbn/core-analytics-browser-mocks", "@kbn/core-ui-settings-browser", + "@kbn/code-editor", ] } diff --git a/packages/kbn-monaco/index.ts b/packages/kbn-monaco/index.ts index 2ebb05bd0e393..e2e3c32d9d0fd 100644 --- a/packages/kbn-monaco/index.ts +++ b/packages/kbn-monaco/index.ts @@ -8,7 +8,15 @@ import './src/register_globals'; -export { monaco } from './src/monaco_imports'; +export { + monaco, + cssConf, + cssLanguage, + markdownConf, + markdownLanguage, + yamlConf, + yamlLanguage, +} from './src/monaco_imports'; export { XJsonLang } from './src/xjson'; export { SQLLang } from './src/sql'; export { ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang } from './src/esql'; diff --git a/packages/kbn-monaco/src/monaco_imports.ts b/packages/kbn-monaco/src/monaco_imports.ts index 9da2a3f4562f3..cebdb7ffa1045 100644 --- a/packages/kbn-monaco/src/monaco_imports.ts +++ b/packages/kbn-monaco/src/monaco_imports.ts @@ -28,4 +28,18 @@ import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution. import 'monaco-editor/esm/vs/basic-languages/xml/xml.contribution.js'; // Needed for basic xml support import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution'; // Needed for yaml support +// config for supported base languages +export { + conf as cssConf, + language as cssLanguage, +} from 'monaco-editor/esm/vs/basic-languages/css/css'; +export { + conf as markdownConf, + language as markdownLanguage, +} from 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; +export { + conf as yamlConf, + language as yamlLanguage, +} from 'monaco-editor/esm/vs/basic-languages/yaml/yaml'; + export { monaco }; diff --git a/packages/kbn-monaco/src/typings.d.ts b/packages/kbn-monaco/src/typings.d.ts new file mode 100644 index 0000000000000..64301b9a59683 --- /dev/null +++ b/packages/kbn-monaco/src/typings.d.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. + */ + +// Monaco languages support +declare module 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; +declare module 'monaco-editor/esm/vs/basic-languages/css/css'; +declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml'; diff --git a/packages/kbn-openapi-generator/index.ts b/packages/kbn-openapi-generator/index.ts index eeaad5343dc9f..711ee4b6269d1 100644 --- a/packages/kbn-openapi-generator/index.ts +++ b/packages/kbn-openapi-generator/index.ts @@ -6,5 +6,6 @@ * Side Public License, v 1. */ +export * from './src/openapi_linter'; export * from './src/openapi_generator'; export * from './src/cli'; diff --git a/packages/kbn-openapi-generator/redocly_linter/config.yaml b/packages/kbn-openapi-generator/redocly_linter/config.yaml new file mode 100644 index 0000000000000..b423d9172b1c8 --- /dev/null +++ b/packages/kbn-openapi-generator/redocly_linter/config.yaml @@ -0,0 +1,27 @@ +# Recommended Redocly CLI ruleset https://redocly.com/docs/cli/rules/recommended/#recommended-ruleset +# Redocly CLI custom plugins https://redocly.com/docs/cli/custom-plugins/ +plugins: + - extra_linter_rules_plugin.js + +rules: + spec: error + spec-strict-refs: warn + no-path-trailing-slash: error + no-identical-paths: error + no-ambiguous-paths: warn + no-unresolved-refs: error + no-enum-type-mismatch: error + component-name-unique: error + path-declaration-must-exist: error + path-not-include-query: error + path-parameters-defined: warn + operation-description: warn + operation-2xx-response: error + operation-4xx-response: warn + operation-operationId: error + operation-operationId-unique: error + operation-summary: warn + operation-operationId-url-safe: error + operation-parameters-unique: error + boolean-parameter-prefixes: warn + extra-linter-rules-plugin/valid-x-modify: error diff --git a/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js b/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js new file mode 100644 index 0000000000000..caef408c366b2 --- /dev/null +++ b/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js @@ -0,0 +1,49 @@ +/* + * 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 KNOWN_X_MODIFY_VALUES = ['partial', 'required', 'requiredOptional']; + +function ValidXModify() { + return { + any: { + leave(node, ctx) { + if (typeof node !== 'object' || !('x-modify' in node)) { + return; + } + + if (!KNOWN_X_MODIFY_VALUES.includes(node['x-modify'])) + ctx.report({ + message: `Only ${KNOWN_X_MODIFY_VALUES.join(', ')} can be used for x-modify`, + location: ctx.location.child('x-modify'), + }); + }, + }, + ref: { + leave(node, ctx) { + if (typeof node !== 'object' || !('x-modify' in node)) { + return; + } + + if (!KNOWN_X_MODIFY_VALUES.includes(node['x-modify'])) + ctx.report({ + message: `Only ${KNOWN_X_MODIFY_VALUES.join(', ')} can be used for x-modify`, + location: ctx.location.child('x-modify'), + }); + }, + }, + }; +} + +module.exports = { + id: 'extra-linter-rules-plugin', + rules: { + oas3: { + 'valid-x-modify': ValidXModify, + }, + }, +}; diff --git a/packages/kbn-openapi-generator/src/cli.ts b/packages/kbn-openapi-generator/src/cli.ts index 9eb91dd9bba94..6361c0a20de3b 100644 --- a/packages/kbn-openapi-generator/src/cli.ts +++ b/packages/kbn-openapi-generator/src/cli.ts @@ -31,6 +31,11 @@ export function runCli() { default: 'zod_operation_schema' as const, choices: AVAILABLE_TEMPLATES, }) + .option('skipLinting', { + describe: 'Whether linting should be skipped', + type: 'boolean', + default: false, + }) .showHelpOnFail(false), (argv) => { generate(argv).catch((err) => { diff --git a/packages/kbn-openapi-generator/src/openapi_generator.ts b/packages/kbn-openapi-generator/src/openapi_generator.ts index 539994a258126..60efd762dade7 100644 --- a/packages/kbn-openapi-generator/src/openapi_generator.ts +++ b/packages/kbn-openapi-generator/src/openapi_generator.ts @@ -17,6 +17,7 @@ import { fixEslint } from './lib/fix_eslint'; import { formatOutput } from './lib/format_output'; import { getGeneratedFilePath } from './lib/get_generated_file_path'; import { removeGenArtifacts } from './lib/remove_gen_artifacts'; +import { lint } from './openapi_linter'; import { getGenerationContext } from './parser/get_generation_context'; import type { OpenApiDocument } from './parser/openapi_types'; import { initTemplateService, TemplateName } from './template_service/template_service'; @@ -25,10 +26,18 @@ export interface GeneratorConfig { rootDir: string; sourceGlob: string; templateName: TemplateName; + skipLinting?: boolean; } export const generate = async (config: GeneratorConfig) => { - const { rootDir, sourceGlob, templateName } = config; + const { rootDir, sourceGlob, templateName, skipLinting } = config; + + if (!skipLinting) { + await lint({ + rootDir, + sourceGlob, + }); + } console.log(chalk.bold(`Generating API route schemas`)); console.log(chalk.bold(`Working directory: ${chalk.underline(rootDir)}`)); diff --git a/packages/kbn-openapi-generator/src/openapi_linter.ts b/packages/kbn-openapi-generator/src/openapi_linter.ts new file mode 100644 index 0000000000000..afd31a77bdee1 --- /dev/null +++ b/packages/kbn-openapi-generator/src/openapi_linter.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +/* eslint-disable no-console */ + +import { resolve } from 'path'; +import globby from 'globby'; +import execa from 'execa'; +import chalk from 'chalk'; +import { REPO_ROOT } from '@kbn/repo-info'; + +export interface LinterConfig { + rootDir: string; + sourceGlob: string; +} + +export const lint = async (config: LinterConfig) => { + const { rootDir, sourceGlob } = config; + + const sourceFilesGlob = resolve(rootDir, sourceGlob); + const schemaPaths = await globby([sourceFilesGlob]); + + console.log(chalk.bold(`Linting API route schemas`)); + + try { + await execa( + './node_modules/.bin/redocly', + [ + 'lint', + '--config=packages/kbn-openapi-generator/redocly_linter/config.yaml', + ...schemaPaths, + ], + { + cwd: REPO_ROOT, + stderr: process.stderr, + stdout: process.stdout, + } + ); + } catch { + throw new Error('Linter failed'); + } +}; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index ab66e1edc445f..69b3f85b70416 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -86,7 +86,7 @@ pageLoadAssetSize: kibanaUsageCollection: 16463 kibanaUtils: 79713 kubernetesSecurity: 77234 - lens: 41000 + lens: 42000 licenseManagement: 41817 licensing: 29004 links: 44490 diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 24966c78960bb..3546fcec41af4 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -39,8 +39,7 @@ import { EuiOutsideClickDetector, EuiToolTip, } from '@elastic/eui'; -import { CodeEditor } from '@kbn/kibana-react-plugin/public'; -import type { CodeEditorProps } from '@kbn/kibana-react-plugin/public'; +import { CodeEditor, CodeEditorProps } from '@kbn/code-editor'; import { textBasedLanguagedEditorStyles, diff --git a/packages/kbn-text-based-editor/tsconfig.json b/packages/kbn-text-based-editor/tsconfig.json index 72240c8aa060d..1c71fc544155d 100644 --- a/packages/kbn-text-based-editor/tsconfig.json +++ b/packages/kbn-text-based-editor/tsconfig.json @@ -24,7 +24,8 @@ "@kbn/expressions-plugin", "@kbn/data-views-plugin", "@kbn/index-management-plugin", - "@kbn/visualization-utils" + "@kbn/visualization-utils", + "@kbn/code-editor", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-ui-shared-deps-src/BUILD.bazel b/packages/kbn-ui-shared-deps-src/BUILD.bazel index cd97c193f9f86..9e62a7418f153 100644 --- a/packages/kbn-ui-shared-deps-src/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-src/BUILD.bazel @@ -35,6 +35,7 @@ webpack_cli( "//packages/kbn-peggy-loader", "//packages/shared-ux/error_boundary", "//packages/kbn-rison", + "//packages/shared-ux/code_editor/impl:code_editor", ], output_dir = True, args = [ diff --git a/packages/kbn-ui-shared-deps-src/src/definitions.js b/packages/kbn-ui-shared-deps-src/src/definitions.js index 9ae258dca6bc8..7480303087b6c 100644 --- a/packages/kbn-ui-shared-deps-src/src/definitions.js +++ b/packages/kbn-ui-shared-deps-src/src/definitions.js @@ -98,6 +98,7 @@ const externals = { classnames: '__kbnSharedDeps__.Classnames', '@tanstack/react-query': '__kbnSharedDeps__.ReactQuery', '@tanstack/react-query-devtools': '__kbnSharedDeps__.ReactQueryDevtools', + '@kbn/code-editor': '__kbnSharedDeps__.KbnCodeEditor', }; module.exports = { distDir, jsFilename, cssDistFilename, externals }; diff --git a/packages/kbn-ui-shared-deps-src/src/entry.js b/packages/kbn-ui-shared-deps-src/src/entry.js index 6ba856cbbc2d1..d0585d0cacc04 100644 --- a/packages/kbn-ui-shared-deps-src/src/entry.js +++ b/packages/kbn-ui-shared-deps-src/src/entry.js @@ -74,3 +74,4 @@ export const History = require('history'); export const Classnames = require('classnames'); export const ReactQuery = require('@tanstack/react-query'); export const ReactQueryDevtools = require('@tanstack/react-query-devtools'); +export const KbnCodeEditor = require('@kbn/code-editor'); diff --git a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx index 7db7ffedfdecf..c59acdc815389 100644 --- a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx @@ -13,7 +13,8 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { getRenderCellValueFn } from './get_render_cell_value'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { CodeEditorProps, KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { CodeEditorProps } from '@kbn/code-editor'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; diff --git a/packages/shared-ux/code_editor/impl/BUILD.bazel b/packages/shared-ux/code_editor/impl/BUILD.bazel new file mode 100644 index 0000000000000..ad571cb379afd --- /dev/null +++ b/packages/shared-ux/code_editor/impl/BUILD.bazel @@ -0,0 +1,37 @@ +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") + +SRCS = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/test_helpers.ts", + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +BUNDLER_DEPS = [ + "@npm//react", + "@npm//tslib", + "@npm//react-monaco-editor", + "@npm//react-resize-detector", +] + +js_library( + name = "code_editor", + package_name = "@kbn/code-editor", + srcs = SRCS + ["package.json"], + deps = BUNDLER_DEPS, + visibility = ["//visibility:public"], +) diff --git a/packages/shared-ux/code_editor/README.mdx b/packages/shared-ux/code_editor/impl/README.mdx similarity index 100% rename from packages/shared-ux/code_editor/README.mdx rename to packages/shared-ux/code_editor/impl/README.mdx diff --git a/packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap similarity index 88% rename from packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap rename to packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap index 790a4f05f8c50..4fb960f82cc7d 100644 --- a/packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap +++ b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap @@ -290,7 +290,7 @@ exports[` is rendered 1`] = ` - is rendered 1`] = `